I've created a line graph with d3.nest() objects, but I need the fill color for each segment to be based on another variable. I thought I could just do it based on the gradient from the data file, but it actually needs to be computed over the distance of the segment. Right now, everything is coming back as one color when it should be
if gradient < -10
color = red
if gradient < -5
color = green
if gradient < 0
color = white
if gradient < 5
color = yellow
if gradient < 10
color = black
else
color = blue
Here's a Plunk
<!DOCTYPE html>
<meta charset="utf-8">
<style>
body {
font: 12px Arial;
}
text.shadow {
stroke: #fff;
stroke-width: 2.5px;
opacity: 0.9;
}
path {
stroke: steelblue;
stroke-width: 2;
fill: none;
}
.axis path,
.axis line {
fill: none;
stroke: grey;
stroke-width: 1;
shape-rendering: crispEdges;
}
.grid .tick {
stroke: lightgrey;
stroke-opacity: 0.7;
shape-rendering: crispEdges;
}
.grid path {
stroke-width: 0;
}
.area {
stroke-width: 0;
}
</style>
<body>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script>
var margin = {top: 30, right: 20, bottom: 35, left: 50},
width = 600 - margin.left - margin.right,
height = 270 - margin.top - margin.bottom;
var color = d3.scale.ordinal()
.domain([-10,-5,0,5,10])
.range(['red','green','white','yellow','black','blue']);
var x = d3.scale.linear().range([0, width]);
var y = d3.scale.linear().range([height, 0]);
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom")
.ticks(5);
var yAxis = d3.svg.axis()
.scale(y)
.orient("left")
.ticks(5);
var area = d3.svg.area()
.x(function(d) { return x(d.distance); })
.y0(height)
.y1(function(d) { return y(d.elevation); });
var valueline = d3.svg.line()
.x(function(d) { return x(d.distance); })
.y(function(d) { return y(d.elevation); });
var svg = d3.select("body")
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform",
"translate(" + margin.left + "," + margin.top + ")");
// function for the x grid lines
function make_x_axis() {
return d3.svg.axis()
.scale(x)
.orient("bottom")
.ticks(5)
}
// function for the y grid lines
function make_y_axis() {
return d3.svg.axis()
.scale(y)
.orient("left")
.ticks(5)
}
// Get the data
d3.csv("data.csv", function(error, data) {
data.forEach(function(d) {
d.distance = +d.distance;
d.elevation = +d.elevation;
d.gradient = +d.gradient;
});
var dataGroup = d3.nest()
.key(function(d) {
return d.grade;
})
.entries(data);
dataGroup.forEach(function(group, i) {
if(i < dataGroup.length - 1) {
group.values.push(dataGroup[i+1].values[0])
}
})
// Scale the range of the data
x.domain(d3.extent(data, function(d) { return d.distance; }));
y.domain([0, d3.max(data, function(d) { return d.elevation; })]);
dataGroup.forEach(function(d, i){
svg.append("path")
.datum(d.values)
.attr("class", "area")
.attr("d", area);
});
svg.selectAll(".area")
.style("fill", function(d) { return color(d.gradient); });
// Draw the x Grid lines
svg.append("g")
.attr("class", "grid")
.attr("transform", "translate(0," + height + ")")
.call(make_x_axis()
.tickSize(-height, 0, 0)
.tickFormat("")
)
// Draw the y Grid lines
svg.append("g")
.attr("class", "grid")
.call(make_y_axis()
.tickSize(-width, 0, 0)
.tickFormat("")
)
// Add the valueline path.
svg.append("path")
.attr("d", valueline(data));
// Add the X Axis
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
// Add the Y Axis
svg.append("g")
.attr("class", "y axis")
.call(yAxis);
// Add the text label for the X axis
svg.append("text")
.attr("transform",
"translate(" + (width/2) + " ," +
(height+margin.bottom) + ")")
.style("text-anchor", "middle")
.text("Distance");
// Add the text label for the Y axis
svg.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("x", margin.top - (height / 2))
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("");
// Add the title
svg.append("text")
.attr("x", (width / 2))
.attr("y", 0 - (margin.top / 2))
.attr("text-anchor", "middle")
.style("font-size", "16px")
.style("text-decoration", "underline")
.text("Elevation Graph");
});
</script>
</body>
The issue is with this call:
svg.selectAll(".area")
.style("fill", function(d) { return color(d.gradient); });
Here, "d" is an array of objects of length one or two depending on the index. I don't know which object's gradient you wish to use, but my naive solution without understanding your data would be to use d[0]. Here's the Plunk.
Related
I am new to d3 and am trying to draw mean line through all the bars in the bar chart but not quite able to achieve that. Below is my code:
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
<title>JS Bin</title>
<style>
body {
font: 10px sans-serif;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.bar {
fill: steelblue;
}
.x.axis path {
display: none;
}
.line {
fill: none;
stroke: #444;
stroke-width: 1.5px;
}
</style>
</head>
<body>
<script src="//cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<script>
var data=[
{"letter": "BU", "higher": .08,"lower": .05},
{"letter": "AU", "higher": .05,"lower": .03},
{"letter": "LA", "higher": .04,"lower": .02}
]
var margin = {top: 20, right: 20, bottom: 30, left: 40},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var formatPercent = d3.format(".0%");
var x = d3.scale.ordinal()
.rangeRoundBands([0, width], .1);
var x2 = d3.scale.ordinal()
.rangeBands([0, width], 0);
var y = d3.scale.linear()
.range([height, 0]);
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left")
.tickFormat(formatPercent);
var svg = d3.select("body").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
data.forEach(function(d) {
d.higher = +d.higher;
d.lower = +d.lower;
});
x.domain(data.map(function(d) { return d.letter; }));
x2.domain(data.map(function(d) { return d.letter; }));
y.domain([0, d3.max(data, function(d) { return d.higher; })]);
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("Frequency");
svg.selectAll(".bar")
.data(data)
.enter().append("rect")
.attr("class", "bar")
.attr("x", function(d) { return x(d.letter); })
.attr("width", x.rangeBand())
.attr("y", function(d) { return y(d.higher); })
.attr("height", function(d) { return height - y(d.higher-d.lower); });
var dataSum = d3.mean(data, function(d) { return (d.higher + d.lower); });
var line = d3.svg.line()
.x(function(d, i) {
return x(d.letter) + i; })
.y(function(d, i) { return y(dataSum/data.length); });
svg.append("path")
.datum(data)
.attr("class", "line")
.attr("d", line);
</script>
</body>
</html>
The proper code is here'http://jsbin.com/beyakumohi/1/edit?html' . The line should pass through center of each bars but it only happens for the 3rd bar and that too it do not cross it. Is there any mistake in my code.
d3.mean will give you the mean value of the full array. Meaning, that in this case you will get the mean of:
data[0].higher + data[0].lower + data[1].higher + data[1].lower + data[2].higher + data[2].lower
In this case I would say it is more appropiate to edit your line function as following
var line = d3.svg.line()
.x(function(d, i) {
return x(d.letter); })
.y(function(d, i) { return y((d.higher + d.lower) / 2); });
I am able to create a Line Chart using a TSV line chart. Now i want to create a mean value Line parallel to x-axis. Please help how to do it
<!DOCTYPE html>
<meta charset="utf-8">
<style>
body {
font: 10px sans-serif;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.x.axis path {
display: none;
}
.line {
fill: none;
stroke: steelblue;
stroke-width: 1.5px;
}
</style>
<body>
<script src="//d3js.org/d3.v3.min.js"></script>
<script>
var margin = {top: 20, right: 20, bottom: 30, left: 50},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var formatDate = d3.time.format("%d-%m-%y");
var x = d3.time.scale()
.range([0, width]);
var y = d3.scale.linear()
.range([height, 0]);
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left");
var line = d3.svg.line()
.x(function(d) { return x(d.date); })
.y(function(d) { return y(d.close); });
var svg = d3.select("body").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
d3.tsv("line.tsv", type, function(error, data) {
if (error) throw error;
x.domain(d3.extent(data, function(d) { return d.date; }));
y.domain(d3.extent(data, function(d) { return d.close; }));
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("Time Difference (sec)");
svg.append("path")
.datum(data)
.attr("class", "line")
.attr("d", line);
});
function type(d) {
d.date = formatDate.parse(d.date);
d.close = +d.close;
return d;
}
</script>
date close
0 1
19-09-15 11
20-09-15 12
21-09-15 2
22-09-15 20
23-09-15 13
24-09-15 4
25-09-15 4
26-09-15 5
27-09-15 1
28-08-16 32
29-08-16 23
01-08-16 12
02-08-16 5
03-08-16 4
04-08-16 10
05-08-16 20
06-08-16 22
07-08-16 1
08-08-16 3
In regards to why what you have done does not work, you are trying to get an element on your page which is identifiable by:
("document.getElementByID(‘TextBoxProductName’).value = arguments[0]", "John")
You probably dont have an element which has that identifiable trait?
When you want to find an element which has an id, you know its going to be unique, so you can quickly/shortly and directly target it as:
element(by.id('TextBoxProductName'))
// or in shorthand
$(#TextBoxProductName)
to send enter text into it, use sendKeys:
$(#TextBoxProductName).sendKeys('John')
Please let us know if the problem you are having isnt the sending of keys, but rather the targeting of the element and we can work on maybe a solution to do with the popup box
Can any one help me to add tool trip in line chart in d3.js
Here is what I have so far:
My Javascript:
var n = 40;
random = d3.random.normal(0, .2),
data = [-2.0236589]; // d3.range(n).map(random);
//alert(data);
var margin = {
top: 20,
right: 20,
bottom: 20,
left: 40
},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var x = d3.scale.linear()
.domain([1, n - 2])
.range([0, width]);
var y = d3.scale.linear()
.domain([-1, 1])
.range([height, 0]);
var line = d3.svg.line()
.interpolate("basis")
.x(function (d, i) {
return x(i);
})
.y(function (d, i) {
return y(d);
});
var svg = d3.select("body").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
svg.append("defs").append("clipPath")
.attr("id", "clip")
.append("rect")
.attr("width", width)
.attr("height", height);
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + y(0) + ")")
.call(d3.svg.axis().scale(x).orient("bottom"));
svg.append("g")
.attr("class", "y axis")
.call(d3.svg.axis().scale(y).orient("left"));
var path = svg.append("g")
.attr("clip-path", "url(#clip)")
.append("path")
.datum(data)
.attr("class", "line")
.attr("d", line);
tick();
function tick() {
// alert(data);
// random();
// console.log(data);
// push a new data point onto the back
data.push(random());
//random();
// redraw the line, and slide it to the left
path.attr("d", line)
// .attr("d", valueline(data))
.attr("transform", null)
.transition()
.duration(500)
.ease("linear")
.attr("transform", function (data) {
return data.length > 40 ? "translate(" + x(0) + ",0)" : "translate(0)"
})
.each("end", tick);
// pop the old data point off the front
//alert(data.length);
if (data.length > 40) {
//alert(data.length);
data.shift();
}
}
CSS:
svg {
font: 10px sans-serif;
}
.line {
fill: none;
stroke: #000;
stroke-width: 1.5px;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
JSFiddle link: http://jsfiddle.net/RajuSahoo/ug6v86cc/1/
Difference chart in D3 js does not show the graph properly.
I have the below data in the tsv file.
for column C there is a value 50 but however the graph stops at approx 30+ on Y axis.
May I know how can I get the graph to be plotted properly.
date A C
20140108 1
20140110 2
20140116 1 3
20140117 1 1
20140120 20 38
20140127 0 1
20140128 0 50
20140130 1 2
20140203 25 2
20140210 3 5
20140211 40 0
20140212 1
20140218 4
Code:
body {
font: 10px sans-serif;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.x.axis path {
display: none;
}
.area.above {
fill: rgb(252,141,89); //for red
}
.area.below {
fill: rgb(145,207,96); //for green
}
.line {
fill: none;
stroke: #000;
stroke-width: 1.5px;
}
</style>
<body>
<!script type="text/javascript" src="d3/d3.v3.min.js"><!/script>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script>
var margin = {top: 30, right: 30, bottom: 50, left: 50},
width = 960 - margin.left - margin.right,
height = 800 - margin.top - margin.bottom;
var parseDate = d3.time.format("%Y%m%d").parse;
var x = d3.time.scale()
.range([0, width]);
var y = d3.scale.linear()
.range([height, 0]);
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left");
var line = d3.svg.area()
.interpolate("basis")
.x(function(d) { return x(d.date); })
.y(function(d) { return y(d["A"]); });
var area = d3.svg.area()
.interpolate("basis")
.x(function(d) { return x(d.date); })
.y1(function(d) { return y(d["A"]); });
var svg = d3.select("body").append("svg") //main svg object which does everything
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
d3.tsv("data.tsv", function(error, data) {
data.forEach(function(d) {
d.date = parseDate(d.date);
d["A"]= +d["A"]; //data here should be in sync with columns in the input file
d["C"] = +d["C"];
});
x.domain(d3.extent(data, function(d) { return d.date; }));
y.domain([
d3.min(data, function(d) { return Math.min(d["A"], d["C"]); }),
d3.max(data, function(d) { return Math.max(d["A"], d["C"]); })
]);
//svg block starts from here
svg.datum(data); //get or set data for individual elements, without computing a join
svg.append("clipPath")
.attr("id", "clip-below")
.append("path")
.attr("d", area.y0(height));
svg.append("clipPath")
.attr("id", "clip-above")
.append("path")
.attr("d", area.y0(0));
svg.append("path")
.attr("class", "area above")
.attr("clip-path", "url(#clip-above)")
.attr("d", area.y0(function(d) { return y(d["C"]); }));
svg.append("path")
.attr("class", "area below")
.attr("clip-path", "url(#clip-below)")
.attr("d", area);
svg.append("path")
.attr("class", "line")
.attr("d", line);
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
// .append ("text")
// .text("New York");
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("count");
});
</script>
I am trying to create multiple series in d3 with different fill colors for the area in between the lines for each series. I have successfully gotten the first series in, and I am confident I can create multiple series, but I can't figure out how to append the fill color of just that series. I've tried to do something along the lines of: .attr("fill","red"); to append the area but this doesn't work. Here is my full code:
<!DOCTYPE html>
<meta charset="utf-8">
<style>
body {
font: 10px sans-serif;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.x.axis path {
display: none;
}
.area {
fill: steelblue;
}
</style>
<body>
<script src="http://d3js.org/d3.v3.js"></script>
<script>
var margin = {top: 20, right: 20, bottom: 30, left: 50},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var parseDate = d3.time.format("%H:%M:%S").parse;
var x = d3.time.scale()
.range([0, width]);
var y = d3.scale.linear()
.range([height, 0]);
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left");
var line = d3.svg.line()
.x(function(d) { return x(d.date); })
.y(function(d) { return y(d.close); });
var area = d3.svg.area()
.x(function(d) { return x(d.date); })
.y0(function(d) { return y(d.low); })
.y1(function(d) { return y(d.high); });
var svg = d3.select("body").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var context = svg.append("g")
.attr('class','container')
d3.csv("data.csv", function(error, data) {
data.forEach(function(d) {
d.date = parseDate(d.date);
d.high = +d.positive;
d.low = +d.positivelow;
});
x.domain(d3.extent(data, function(d) { return d.date; }));
<!--y.domain(d3.extent(data, function(d) { return d.close; }));-->
<!--y.domain([d3.min(data, function(d) { return d.low; }), d3.max(data, function(d) { return d.high; })]);-->
y.domain([1720,1780])
svg.append("path")
.datum(data)
.attr("class", "area")
.attr("d", area);
<!--(This line below doesn't work)-->
<!--.attr("fill","red");-->
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("Some Y Title");
});
</script>