d3.time.format.multi is not a function - javascript
I need to design a streamgraph using d3.js and I started to experiment with the code hosted on GitHub. Since my dataset is expected to have a varying range between the minimum and maximum values for date (it can be a period of one month or several years), I decided to use multi-scale format for the ticks on my x-axis instead of fixing the format and interval into weeks, months, years, etc. For example, if I leave the tick format the same way it is given in the sample code on GitHub
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom")
.ticks(d3.time.weeks);
and if the range of dates in my dataset spans for several years, the legend of the x-axis becomes crowded and unreadable.
I tried to use multi-scale format, but the visualization will not be drawn and the Dev tool of my browser returns the following error:
d3.time.format.multi is not a function
I sincerely hope someone can suggest me a solution for this problem.
Below you can see my full code:
<!DOCTYPE html>
<meta charset="utf-8">
<style>
body {
font: 10px sans-serif;
}
.chart {
background: #fff;
}
p {
font: 12px helvetica;
}
.axis path, .axis line {
fill: none;
stroke: #000;
stroke-width: 2px;
shape-rendering: crispEdges;
}
button {
position: absolute;
right: 50px;
top: 10px;
}
</style>
<body>
<script src="http://d3js.org/d3.v2.js"></script>
<div class="chart">
</div>
<script>
chart("tutorial.csv", "orange");
var datearray = [];
var colorrange = [];
function chart(csvpath, color) {
if (color == "blue") {
colorrange = ["#045A8D", "#2B8CBE", "#74A9CF", "#A6BDDB", "#D0D1E6", "#F1EEF6"];
}
else if (color == "pink") {
colorrange = ["#980043", "#DD1C77", "#DF65B0", "#C994C7", "#D4B9DA", "#F1EEF6"];
}
else if (color == "orange") {
colorrange = ["#B30000", "#E34A33", "#FC8D59", "#FDBB84", "#FDD49E", "#FEF0D9"];
}
strokecolor = colorrange[0];
var format = d3.time.format("%m/%d/%y");
var margin = {top: 20, right: 40, bottom: 30, left: 30};
var width = document.body.clientWidth - margin.left - margin.right;
var height = 400 - margin.top - margin.bottom;
var tooltip = d3.select("body")
.append("div")
.attr("class", "remove")
.style("position", "absolute")
.style("z-index", "20")
.style("visibility", "hidden")
.style("top", "30px")
.style("left", "55px");
var customTimeFormat = d3.time.format.multi([
[".%L", function(d) { return d.getMilliseconds(); }],
[":%S", function(d) { return d.getSeconds(); }],
["%I:%M", function(d) { return d.getMinutes(); }],
["%I %p", function(d) { return d.getHours(); }],
["%a %d", function(d) { return d.getDay() && d.getDate() != 1; }],
["%b %d", function(d) { return d.getDate() != 1; }],
["%B", function(d) { return d.getMonth(); }],
["%Y", function() { return true; }]
]);
var x = d3.time.scale()
.range([0, width]);
var y = d3.scale.linear()
.range([height-10, 0]);
var z = d3.scale.ordinal()
.range(colorrange);
var yAxis = d3.svg.axis()
.scale(y);
var yAxisr = d3.svg.axis()
.scale(y);
var stack = d3.layout.stack()
.offset("silhouette")
.values(function(d) { return d.values; })
.x(function(d) { return d.date; })
.y(function(d) { return d.value; });
var nest = d3.nest()
.key(function(d) { return d.key; });
var area = d3.svg.area()
.interpolate("cardinal")
.x(function(d) { return x(d.date); })
.y0(function(d) { return y(d.y0); })
.y1(function(d) { return y(d.y0 + d.y); });
var svg = d3.select(".chart").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 graph = d3.csv(csvpath, function(data) {
data.forEach(function(d) {
d.date = format.parse(d.date);
d.value = +d.value;
});
x.domain(d3.extent(data, function(d) { return d.date; }));
y.domain([0, d3.max(data, function(d) { return d.y0 + d.y; })]);
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom")
.tickFormat(customTimeFormat);
var layers = stack(nest.entries(data));
svg.selectAll(".layer")
.data(layers)
.enter().append("path")
.attr("class", "layer")
.attr("d", function(d) { return area(d.values); })
.style("fill", function(d, i) { return z(i); });
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg.append("g")
.attr("class", "y axis")
.attr("transform", "translate(" + width + ", 0)")
.call(yAxis.orient("right"));
svg.append("g")
.attr("class", "y axis")
.call(yAxis.orient("left"));
svg.selectAll(".layer")
.attr("opacity", 1)
.on("mouseover", function(d, i) {
svg.selectAll(".layer").transition()
.duration(250)
.attr("opacity", function(d, j) {
return j != i ? 0.6 : 1;
})})
.on("mousemove", function(d, i) {
mousex = d3.mouse(this);
mousex = mousex[0];
var invertedx = x.invert(mousex);
invertedx = invertedx.getMonth() + invertedx.getDate();
var selected = (d.values);
for (var k = 0; k < selected.length; k++) {
datearray[k] = selected[k].date
datearray[k] = datearray[k].getMonth() + datearray[k].getDate();
}
mousedate = datearray.indexOf(invertedx);
pro = d.values[mousedate].value;
d3.select(this)
.classed("hover", true)
.attr("stroke", strokecolor)
.attr("stroke-width", "0.5px"),
tooltip.html( "<p>" + d.key + "<br>" + pro + "</p>" ).style("visibility", "visible");
})
.on("mouseout", function(d, i) {
svg.selectAll(".layer")
.transition()
.duration(250)
.attr("opacity", "1");
d3.select(this)
.classed("hover", false)
.attr("stroke-width", "0px"), tooltip.html( "<p>" + d.key + "<br>" + pro + "</p>" ).style("visibility", "hidden");
})
var vertical = d3.select(".chart")
.append("div")
.attr("class", "remove")
.style("position", "absolute")
.style("z-index", "19")
.style("width", "1px")
.style("height", "380px")
.style("top", "10px")
.style("bottom", "30px")
.style("left", "0px")
.style("background", "#fff");
d3.select(".chart")
.on("mousemove", function(){
mousex = d3.mouse(this);
mousex = mousex[0] + 5;
vertical.style("left", mousex + "px" )})
.on("mouseover", function(){
mousex = d3.mouse(this);
mousex = mousex[0] + 5;
vertical.style("left", mousex + "px")});
});
}
</script>
For start, I'm using the dataset from GitHub's sample:
key,value,date
AR,0.1,01/08/13
AR,0.15,01/09/13
AR,0.35,01/10/13
AR,0.38,01/11/13
AR,0.22,01/12/13
AR,0.16,01/13/13
AR,0.07,01/14/13
AR,0.02,01/15/13
AR,0.17,01/16/13
AR,0.33,01/17/13
AR,0.4,01/18/13
AR,0.32,01/19/13
AR,0.26,01/20/13
AR,0.35,01/21/13
AR,0.4,01/22/13
AR,0.32,01/23/13
AR,0.26,01/24/13
AR,0.22,01/25/13
AR,0.16,01/26/13
AR,0.22,01/27/13
AR,0.1,01/28/13
DJ,0.35,01/08/13
DJ,0.36,01/09/13
DJ,0.37,01/10/13
DJ,0.22,01/11/13
DJ,0.24,01/12/13
DJ,0.26,01/13/13
DJ,0.34,01/14/13
DJ,0.21,01/15/13
DJ,0.18,01/16/13
DJ,0.45,01/17/13
DJ,0.32,01/18/13
DJ,0.35,01/19/13
DJ,0.3,01/20/13
DJ,0.28,01/21/13
DJ,0.27,01/22/13
DJ,0.26,01/23/13
DJ,0.15,01/24/13
DJ,0.3,01/25/13
DJ,0.35,01/26/13
DJ,0.42,01/27/13
DJ,0.42,01/28/13
MS,0.21,01/08/13
MS,0.25,01/09/13
MS,0.27,01/10/13
MS,0.23,01/11/13
MS,0.24,01/12/13
MS,0.21,01/13/13
MS,0.35,01/14/13
MS,0.39,01/15/13
MS,0.4,01/16/13
MS,0.36,01/17/13
MS,0.33,01/18/13
MS,0.43,01/19/13
MS,0.4,01/20/13
MS,0.34,01/21/13
MS,0.28,01/22/13
MS,0.26,01/23/13
MS,0.37,01/24/13
MS,0.41,01/25/13
MS,0.46,01/26/13
MS,0.47,01/27/13
MS,0.41,01/28/13
RC,0.1,01/08/13
RC,0.15,01/09/13
RC,0.35,01/10/13
RC,0.38,01/11/13
RC,0.22,01/12/13
RC,0.16,01/13/13
RC,0.07,01/14/13
RC,0.02,01/15/13
RC,0.17,01/16/13
RC,0.33,01/17/13
RC,0.4,01/18/13
RC,0.32,01/19/13
RC,0.26,01/20/13
RC,0.35,01/21/13
RC,0.4,01/22/13
RC,0.32,01/23/13
RC,0.26,01/24/13
RC,0.22,01/25/13
RC,0.16,01/26/13
RC,0.22,01/27/13
RC,0.1,01/28/13
CG,0.1,01/08/13
CG,0.15,01/09/13
CG,0.35,01/10/13
CG,0.38,01/11/13
CG,0.22,01/12/13
CG,0.16,01/13/13
CG,0.07,01/14/13
CG,0.02,01/15/13
CG,0.17,01/16/13
CG,0.33,01/17/13
CG,0.4,01/18/13
CG,0.32,01/19/13
CG,0.26,01/20/13
CG,0.35,01/21/13
CG,0.4,01/22/13
CG,0.32,01/23/13
CG,0.26,01/24/13
CG,0.22,01/25/13
CG,0.16,01/26/13
CG,0.22,01/27/13
CG,0.1,01/28/13
RI,0.1,01/08/13
RI,0.15,01/09/13
RI,0.35,01/10/13
RI,0.38,01/11/13
RI,0.22,01/12/13
RI,0.16,01/13/13
RI,0.07,01/14/13
RI,0.02,01/15/13
RI,0.17,01/16/13
RI,0.33,01/17/13
RI,0.4,01/18/13
RI,0.32,01/19/13
RI,0.26,01/20/13
RI,0.35,01/21/13
RI,0.4,01/22/13
RI,0.32,01/23/13
RI,0.26,01/24/13
RI,0.22,01/25/13
RI,0.16,01/26/13
RI,0.22,01/27/13
RI,0.1,01/28/13
Your code is using d3 version 2. Try using the third version instead :
http://d3js.org/d3.v3.js
Related
Last tick label does not appear in D3 Line Chart
I'm trying to write a generic multiline chart function based on Mike Bostock's example (https://bl.ocks.org/mbostock/3884955). I'm facing an issue wherein, the last tick label on my Monthly graph x-axis does not show up. The last tick appears fine on the Weekly graph x-axis. JS Fiddle Link: http://jsfiddle.net/Q5Jag/11879/ I'm suspecting the issue here could be due to the range specified for the x-axis which for some reason ignores the last value. But I'm not exactly sure what is going on here. Could anyone help me debug ? Here is my code: function renderMultiLineChart(datafile, chartDiv, xAxisLabel, yAxisLabel, graphCadence){ var margin = {top: 20, right: 60, bottom: 80, left: 60}, width = 760 - margin.left - margin.right, height = 400 - margin.top - margin.bottom; var parseDate = d3.timeParse("%m/%d/%y"); var x = d3.scaleUtc() .range([0, width]); var y = d3.scaleLinear() .range([height, 0]); var color = d3.scaleOrdinal(d3.schemeCategory10); //var xAxis = d3.axisBottom(x).tickFormat(function(d){ return d.x;}); switch(graphCadence) { case "Daily": var xAxis = d3.axisBottom(x).ticks(d3.timeDay.every(1)).tickFormat(d3.timeFormat("%m/%d")) break; case "Weekly": var xAxis = d3.axisBottom(x).ticks(d3.timeSaturday.every(1)).tickFormat(d3.timeFormat("%m/%d")) break; case "Monthly": //var xAxis = d3.axisBottom(x).ticks(d3.timeDay.every(1)) var xAxis = d3.axisBottom(x).ticks(d3.timeMonth.every(1)).tickFormat(d3.utcFormat("%m/%d")) break; } var yAxis = d3.axisLeft(y); var line = d3.line() .x(function(d) { return x(d.date); }) .y(function(d) { return y(d.count); }) var div = d3.select(chartDiv).append("div") .attr("class", "tooltip") .style("opacity", 0); var svg = d3.select(chartDiv).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 + ")"); //https://pharos-rest-service-iad.iad.proxy.amazon.com/s3/tool.csv d3.csv(datafile, function(error, data) { color.domain(d3.keys(data[0]).filter(function(key) { return key !== "date"; })); data.forEach(function(d) { //console.log(d); d.date = parseDate(d.date); }); var datapoints = color.domain().map(function(name) { return { name: name, values: data.map(function(d) { return {date: d.date, count: +d[name]}; }) }; }); console.log(data); x.domain(d3.extent(data, function(d) { return d.date; })); y.domain([ d3.min(datapoints, function(c) { return d3.min(c.values, function(v) { return v.count; }); }), d3.max(datapoints, function(c) { return d3.max(c.values, function(v) { return v.count; }); }) ]); svg.append("g") .attr("class", "x axis") .attr("transform", "translate(0," + height + ")") .call(xAxis) .selectAll("text") .attr("dx", "-.8em") .attr("dy", ".15em") .style("text-anchor", "end") .attr("transform", "rotate(-45)"); // text label for the x axis svg.append("text") .attr("transform", "translate(" + (width/2) + " ," + (height + margin.top + 30) + ")") .style("text-anchor", "middle") .text(xAxisLabel); 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") .style("fill", "black") // set the line colour .text(yAxisLabel); var datapoint = svg.selectAll(".datapoint") .data(datapoints) .enter().append("g") .attr("class", "datapoint"); datapoint.append("path") .attr("class", "line") .attr("d", function(d) { return line(d.values); }) .style("stroke", function(d) { return color(d.name); }); j = -1; datapoint.selectAll("circle") .data(function(d){return d.values}) .enter() .append("circle") .attr("r", 3) .attr("cx", function(d,i) { return x(d.date); }) .attr("cy", function(d) { return y(d.count); }) .on("mouseover", function(d) { div.transition() .duration(200) .style("opacity", 1); div.html("<b>"+d.count+"</b>") .style("left", (d3.event.pageX) + "px") .style("top", (d3.event.pageY - 28) + "px"); }) .on("mouseout", function(d) { div.transition() .duration(500) .style("opacity", 0); }) .style("fill", function(d,i) { if (i == 0) { j++ }; return color(datapoints[j].name); }); var legendRectSize = 8; var legendSpacing = 80; var legendHolder = svg.append('g') // translate the holder to the right side of the graph .attr('transform', "translate(" + (100+margin.left+margin.right) + ","+(height+margin.bottom-20)+")") var legend = legendHolder.selectAll('.legend') .data(color.domain()) .enter() .append('g') .attr('class', 'legend') .attr("transform", function (d, i) { if (i === 0) { dataL = legendRectSize + legendSpacing return "translate(0,0)" } else { var newdataL = dataL dataL += legendRectSize + legendSpacing return "translate(" + (newdataL) + ",0)" } }); legend.append('rect') .attr('width', legendRectSize) .attr('height', legendRectSize) .style('fill', color) .style('stroke', color); legend.append('text') .attr('x', legendRectSize + 5) .attr('y', legendRectSize) .text(function(d) { return d; }); }); } renderMultiLineChart("https://gist.githubusercontent.com/techyogii/323024b01c1eb4d0c07637e183e1e6d7/raw/422ed207cc2c38426fa726795ecd963f153135dd/app_usage","div#multiChartMonthly","Snapshot Date","Metric Count","Monthly") renderMultiLineChart("https://gist.githubusercontent.com/techyogii/8ed38bdb3b8e44194ee8570ef9cc5b75/raw/d0c85aaf9eaa7e8819fd6e6e210885b0cfa6f47d/app_usage_weekly","div#multiChartWeekly","Snapshot Date","Metric Count","Weekly") 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; } div.tooltip { position: absolute; text-align: center; /*width: 60px; height: 28px;*/ padding: 4px; font: 14px sans-serif; background: lightsteelblue; border: 0px; border-radius: 10px; pointer-events: none; } .legend { font-size: 12px; } rect { stroke-width: 2; } <script src="https://d3js.org/d3.v4.min.js"></script> <div id="multiChartWeekly"> <div id="multiChartMonthly"> Thanks, Yogesh
I believe the problem lies in a misalignment between how d3.timeMonth works and how your data is formatted. You see that d3.timeMonth is labeling the first of every month, whereas the data is grouped on the last day of every month. So when you call x.domain(d3.extent(data, function(d) { return d.date; }));, the last data point's date is less than the next label would have been. One potential solution is to change your parse function to bump all your month dates forward by one day to make them line up with the first of the month. See below. To remove any dates that end mid-month, you can filter the data set after parsing dates to clean it up. function renderMultiLineChart(datafile, chartDiv, xAxisLabel, yAxisLabel, graphCadence){ var margin = {top: 20, right: 60, bottom: 80, left: 60}, width = 760 - margin.left - margin.right, height = 400 - margin.top - margin.bottom; var parseDate = function(dateString){ if(graphCadence == "Monthly"){ var date = new Date(dateString); date.setDate(date.getDate()+1); return date; } return d3.timeParse("%m/%d/%y")(dateString); } var x = d3.scaleUtc() .range([0, width]); var y = d3.scaleLinear() .range([height, 0]); var color = d3.scaleOrdinal(d3.schemeCategory10); //var xAxis = d3.axisBottom(x).tickFormat(function(d){ return d.x;}); switch(graphCadence) { case "Daily": var xAxis = d3.axisBottom(x).ticks(d3.timeDay.every(1)).tickFormat(d3.timeFormat("%m/%d")) break; case "Weekly": var xAxis = d3.axisBottom(x).ticks(d3.timeSaturday.every(1)).tickFormat(d3.timeFormat("%m/%d")) break; case "Monthly": //var xAxis = d3.axisBottom(x).ticks(d3.timeDay.every(1)) var xAxis = d3.axisBottom(x).ticks(d3.timeMonth.every(1)).tickFormat(d3.utcFormat("%m/%d")) break; } var yAxis = d3.axisLeft(y); var line = d3.line() .x(function(d) { return x(d.date); }) .y(function(d) { return y(d.count); }) var div = d3.select(chartDiv).append("div") .attr("class", "tooltip") .style("opacity", 0); var svg = d3.select(chartDiv).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 + ")"); //https://pharos-rest-service-iad.iad.proxy.amazon.com/s3/tool.csv d3.csv(datafile, function(error, data) { color.domain(d3.keys(data[0]).filter(function(key) { return key !== "date"; })); data.forEach(function(d) { d.date = parseDate(d.date); }); if(graphCadence == "Monthly"){ data = data.filter(function(d){ return d.date.getDate() == 1 }); } var datapoints = color.domain().map(function(name) { return { name: name, values: data.map(function(d) { return {date: d.date, count: +d[name]}; }) }; }); x.domain(d3.extent(data, function(d) { return d.date; })); y.domain([ d3.min(datapoints, function(c) { return d3.min(c.values, function(v) { return v.count; }); }), d3.max(datapoints, function(c) { return d3.max(c.values, function(v) { return v.count; }); }) ]); svg.append("g") .attr("class", "x axis") .attr("transform", "translate(0," + height + ")") .call(xAxis) .selectAll("text") .attr("dx", "-.8em") .attr("dy", ".15em") .style("text-anchor", "end") .attr("transform", "rotate(-45)"); // text label for the x axis svg.append("text") .attr("transform", "translate(" + (width/2) + " ," + (height + margin.top + 30) + ")") .style("text-anchor", "middle") .text(xAxisLabel); 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") .style("fill", "black") // set the line colour .text(yAxisLabel); var datapoint = svg.selectAll(".datapoint") .data(datapoints) .enter().append("g") .attr("class", "datapoint"); datapoint.append("path") .attr("class", "line") .attr("d", function(d) { return line(d.values); }) .style("stroke", function(d) { return color(d.name); }); j = -1; datapoint.selectAll("circle") .data(function(d){return d.values}) .enter() .append("circle") .attr("r", 3) .attr("cx", function(d,i) { return x(d.date); }) .attr("cy", function(d) { return y(d.count); }) .on("mouseover", function(d) { div.transition() .duration(200) .style("opacity", 1); div.html("<b>"+d.count+"</b>") .style("left", (d3.event.pageX) + "px") .style("top", (d3.event.pageY - 28) + "px"); }) .on("mouseout", function(d) { div.transition() .duration(500) .style("opacity", 0); }) .style("fill", function(d,i) { if (i == 0) { j++ }; return color(datapoints[j].name); }); var legendRectSize = 8; var legendSpacing = 80; var legendHolder = svg.append('g') // translate the holder to the right side of the graph .attr('transform', "translate(" + (100+margin.left+margin.right) + ","+(height+margin.bottom-20)+")") var legend = legendHolder.selectAll('.legend') .data(color.domain()) .enter() .append('g') .attr('class', 'legend') .attr("transform", function (d, i) { if (i === 0) { dataL = legendRectSize + legendSpacing return "translate(0,0)" } else { var newdataL = dataL dataL += legendRectSize + legendSpacing return "translate(" + (newdataL) + ",0)" } }); legend.append('rect') .attr('width', legendRectSize) .attr('height', legendRectSize) .style('fill', color) .style('stroke', color); legend.append('text') .attr('x', legendRectSize + 5) .attr('y', legendRectSize) .text(function(d) { return d; }); }); } renderMultiLineChart("https://gist.githubusercontent.com/JstnPwll/5a24137a36c9246cf065c58d7f5bb5a5/raw/ff986ee88338e99d10ab93035ffacd3ffe92fd4e/gistfile1.txt","div#multiChartMonthly","Snapshot Date","Metric Count","Monthly") renderMultiLineChart("https://gist.githubusercontent.com/techyogii/8ed38bdb3b8e44194ee8570ef9cc5b75/raw/d0c85aaf9eaa7e8819fd6e6e210885b0cfa6f47d/app_usage_weekly","div#multiChartWeekly","Snapshot Date","Metric Count","Weekly") 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; } div.tooltip { position: absolute; text-align: center; /*width: 60px; height: 28px;*/ padding: 4px; font: 14px sans-serif; background: lightsteelblue; border: 0px; border-radius: 10px; pointer-events: none; } .legend { font-size: 12px; } rect { stroke-width: 2; } <script src="https://d3js.org/d3.v4.min.js"></script> <div id="multiChartWeekly"> <div id="multiChartMonthly">
How to properly calculate width for D3 Siluohette stacked Area chart
Hopefully Mike Bostock comes swinging in to my rescue on this one. (EDIT: With the help of Andrea Crawford's answer below this is the working version) JS Fiddle: https://jsfiddle.net/dfcarter/kd0dkrL8/ I have written a chart in d3 to allow on the fly user changes (colors, selected data, etc) Well it is mainly working but when you remove the lower ordinals it stops centering on the graph and starts to creep downward. Looks Fine - removing the first 3 seems fine Looks Unacceptable - removing the Last 3 and the chart is toward the bottom of the graph area The Core of the D3 for reference: (The Fiddle works correctly I don't see why the external reference to spectrum is not working so look at the fiddle) var $pop = $('#my_custom_menu'), notHov = 1; // Hover flag $pop.hover(function() { notHov ^= 1; }); // Toggle flag on hover $(document).on('mouseup keyup', function(e) { if (notHov || e.which == 27) $pop.fadeOut(); }); /////// CALL POPUP $('.my_custom_menu').click(function() { $pop.stop().fadeIn(); }); function updateStream(color) { var label1 = d3.selectAll(".layer") .filter(function(d, i) { return i === clickIndex; }) .style("fill", color); } $("#showPalette").spectrum({ showPalette: true, palette: [ ['black', 'white', 'blanchedalmond'], ['rgb(255, 128, 0);', 'hsv 100 70 50', 'lightyellow'] ], change: updateStream }); var clickIndex = 0; $("#textDisplayName").keyup(function(event) { if (event.keyCode == 13) { //alert(eval($("#stream").val) + " , " + eval($("#textDisplayname").val)); var newValue = document.getElementById("textDisplayName").value; var label1 = d3.selectAll("text") .filter(function(d, i) { return i === clickIndex; }) .text(newValue); } }); chart("data.csv", "blue"); var datearray = []; var colorrange = []; function csv(url, callback) { d3.text(url, function(text) { callback(text && d3.csv.parse(text)); }); } function drawgrid() { } function chart(csvpath, color) { if (color == "blue") { colorrange = ["#045A8D", "#2B8CBE", "#74A9CF", "#A6BDDB", "#D0D1E6", "#F1EEF6"]; } else if (color == "pink") { colorrange = ["#980043", "#DD1C77", "#DF65B0", "#C994C7", "#D4B9DA", "#F1EEF6"]; } else if (color == "orange") { colorrange = ["#B30000", "#E34A33", "#FC8D59", "#FDBB84", "#FDD49E", "#FEF0D9"]; } strokecolor = colorrange[0]; var format = d3.time.format("%m/%d/%y"); var margin = { top: 20, right: 40, bottom: 30, left: 30 }; var width = document.body.clientWidth - margin.left - margin.right - 200; var height = 400 - margin.top - margin.bottom; var tooltip = d3.select("body") .append("div") .attr("class", "remove") .style("position", "absolute") .style("z-index", "20") .style("visibility", "hidden") .style("top", "30px") .style("left", "55px"); var x = d3.time.scale() .range([0, width]); var y = d3.scale.linear() .range([height - 10, 0]); var getColor = d3.scale.ordinal() .range(colorrange); var xAxis = d3.svg.axis() .scale(x) .orient("bottom") .ticks(d3.time.weeks); var yAxis = d3.svg.axis() .scale(y); var yAxisr = d3.svg.axis() .scale(y); var stack = d3.layout.stack() .offset("silhouette") .values(function(d) { return d.values; }) .x(function(d) { return d.date; }) .y(function(d) { return d.value; }); var nest = d3.nest() .key(function(d) { return d.key; }); var area = d3.svg.area() .interpolate("cardinal") .x(function(d) { return x(d.date); }) .y0(function(d) { return y(d.y0); }) .y1(function(d) { return y(d.y0 + d.y); }); var svg = d3.select(".chart").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 randomData() { return Math.random() * 9; } var dates = ["07/08/2016", "07/09/2016", "07/10/2016", "07/11/2016", "07/12/2016", "07/13/2016", "07/14/2016", "07/15/2016", "07/16/2016", "07/17/2016", "07/18/2016"]; var numberOfSeries = 7, numberOfDataPoint = 7, data = []; for (var i = 0; i < numberOfSeries; ++i) { for (var j = 0; j < numberOfDataPoint; ++j) { data.push({ key: i, value: randomData(), date: Date.parse(dates[j]) }); } } var layerData = nest.entries(data); var checkholder = d3.select("#checkboxHolder") var legend = checkholder.selectAll(".legend") .data(layerData) .enter().append("div") legend.append("input") .attr("type", "checkbox") .attr("id", function(d, i) { return "check" + i }); legend.append("label") .attr("for", function(d, i) { return "check" + i }) .attr("y", 9) .attr("dy", ".35em") .style("text-anchor", "end") .html(function(d) { return d.key; }); legend.on('change', function(d) { d.disabled = !d.disabled; d3.transition().duration(600).each(redraw); }); var xaxisnode = svg.append("g") .attr("class", "x axis") .attr("transform", "translate(0," + height + ")") .call(xAxis); var yaxisnode = svg.append("g") .attr("class", "y axis") .attr("transform", "translate(" + width + ", 0)") .call(yAxis.orient("right")); //svg.append("g") // .attr("class", "y axis") // .call(yAxis.orient("left")); function redraw() { var activeLayers = layerData.filter(function(d1) { return !d1.disabled; }); var layers = stack(activeLayers); x.domain(d3.extent(data, function(d) { return d.date; })); y.domain([0, d3.max(data, function(d) { if (!d.disabled) return d.y0 + d.y; })]); svg.selectAll(".layergroup").remove(); var layergroup = svg.selectAll(".layergroup") .data(layers) .enter().append("g") .attr("class", "layergroup"); var paths = layergroup.append("path") .attr("class", "layer") .attr("d", function(d) { return area(d.values); }) .style("fill", function(d, i) { return getColor(i); }); layergroup.append("text") .datum(function(d) { return { name: d.key, value: d.values[d.values.length - 1] }; }) .attr("transform", function(d) { return "translate(" + x(d.value.date) + "," + y(d.value.y0 + d.value.y / 2) + ")"; }) .attr("x", -6) .attr("dy", ".35em") .attr("class", "pathLabel") .text(function(d) { return d.name; }); //var clickIndex = 0; //paths.on("click", function (d, i) { // clickIndex = i; // svg.selectAll("text").filter(function (d, i) { return i === clickIndex }).attr("transform", function (d) { var coords = d3.mouse(svg.node()); return "translate(" + coords[0] + "," + coords[1] + ")"; }) //}); xaxisnode.call(xAxis); yaxisnode.call(yAxis.orient("right")); const drag = d3.behavior.drag() .origin(function(d) { return d; }) .on("dragstart", dragstarted) .on("drag", dragged) .on("dragend", dragended) function dragstarted(d) { d3.event.sourceEvent.stopPropagation(); } var dragIndex = 0; function dragged(d, i) { dragindex = i; const elem = svg.selectAll(".pathLabel").filter(function(d, i) { return i === dragindex; }); elem.attr('transform', function(d) { var coords = d3.mouse(svg.node()); return "translate(" + coords[0] + "," + coords[1] + ")"; }); //elem.attr('y', +elem.attr('y') + d3.event.dy) } function dragended(d) {} svg.selectAll(".layer") .attr("opacity", 1) .on("mouseover", function(d, i) { svg.selectAll(".layer").transition() .duration(250) .attr("opacity", function(d, j) { return j != i ? 0.6 : 1; }) }) .on("mousemove", function(d, i) { mousex = d3.mouse(this); mousex = mousex[0]; var invertedx = x.invert(mousex); invertedx = invertedx.getMonth() + invertedx.getDate(); var selected = (d.values); for (var k = 0; k < selected.length; k++) { datearray[k] = selected[k].date datearray[k] = datearray[k].getMonth() + datearray[k].getDate(); } mousedate = datearray.indexOf(invertedx); pro = d.values[mousedate].value; mouse = d3.mouse(d3.select("#letable").node()); d3.select(this) .classed("hover", true) .attr("stroke", strokecolor) .attr("stroke-width", "0.5px"), tooltip.html("<p>" + d.key + "<br>" + pro + "</p>").style("visibility", "visible").style("left", (mouse[0] + 50) + "px").style("top", (mouse[1] + 30) + "px"); }) .on("mouseout", function(d, i) { svg.selectAll(".layer") .transition() .duration(250) .attr("opacity", "1"); d3.select(this) .classed("hover", false) .attr("stroke-width", "0px"), tooltip.html("<p>" + d.key + "<br>" + pro + "</p>").style("visibility", "hidden"); }) .on("contextmenu", function(data, index) { var position = d3.mouse(this); d3.select('#my_custom_menu') .style('position', 'absolute') .style('left', position[0] + "px") .style('top', position[1] + "px") .style('display', 'block'); d3.event.preventDefault(); //d3.select('#stream') // .attr("value", index); clickIndex = index; $('#textDisplayName') .val(data.key); }).call(drag); //d3.select('svg') // .selectAll('text') // .data(labels) // .enter() // .append('text') // .text(d => d) // .attr('fill', 'green') // .attr('x', (d, i) => 10 + i * 30) // .attr('y', (d, i) => 15 + i * 30) // .call(drag) var vertical = d3.select(".chart") .append("div") .attr("class", "remove") .style("position", "absolute") .style("z-index", "19") .style("width", "1px") .style("height", "380px") .style("top", "10px") .style("bottom", "30px") .style("left", "0px") .style("background", "#ccc"); d3.select(".chart") .on("mousemove", function() { mousex = d3.mouse(d3.select("#letable").node()); mousex = mousex[0] + 5; vertical.style("left", mousex + "px") }) .on("mouseover", function() { mousex = d3.mouse(d3.select("#letable").node()); mousex = mousex[0] + 5; vertical.style("left", mousex + "px") }); } redraw(); } body { font: 10px "segoe ui"; } .chart { background: #fff; } p { font: 12px "segoe ui"; } .axis path, .axis line { fill: none; stroke: #CCC; stroke-width: 2px; shape-rendering: crispEdges; } .pathLabel { font: bold 16px "Segoe UI"; color: black; text-shadow: 0 0 3px #FFF; } button { position: absolute; right: 50px; top: 10px; } #my_custom_menu { display: none; padding: 15px 25px; width: 220px; background: #fff; border-radius: 4px; box-shadow: 0 3px 3px -2px #024; } <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/2.6.0/d3.min.js"></script> <!DOCTYPE html> <body> <script src="https://bgrins.github.io/spectrum/spectrum.js"></script> <script src="https://d3js.org/d3.v2.js"></script> <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script> <link href="https://bgrins.github.io/spectrum/spectrum.css" rel="stylesheet" /> <table id="letable"> <tr> <td> <div id="checkboxHolder" style="width:200px;height:400px;overflow:auto;"> </div> </td> <td> <div class="chart" style="width:700px;height:400px"> </div> </td> </tr> </table> <div id="my_custom_menu"> <input id="textDisplayName" type="text" /> <br /> <input id="showPalette" type="text" /> <br /> <input type="hidden" id="stream" value="" /> </div> </body>
I'm not an expert on D3 so you may still want to wait for Mr. Bostock, but I think your issue is that inside your redraw function, you have this code: y.domain([0, d3.max(data, function(d) { if (!d.disabled) return d.y0 + d.y; })]); but if you look at the value of d, it doesn't actually have a disabled property. You could add a disabled property to the values at the same time you add it to the parent: legend.on('change', function(d) { d.disabled = !d.disabled; $.each(d.values, function(){ this.disabled = d.disabled; }); d3.transition().duration(600).each(redraw); }); There's probably a more elegant way to do that, but it seems to fix the issue.
d3 v4 version of stack function x and y
I am converting some v2 code to v4 and I am stuck at this point. where does the x an y functions go for v4? Also is this the right way to create nested values? Thanks d3.stack() .offset(d3.stackOffsetSilhouette) .value(function(d) { return d.values; }) .x(function(d) { return d.date; }) .y(function(d) { return d.value; }); var nest = d3.nest() .key(function(d) { return d.key; }); var layers = stack(nest.entries(mainVal)); Edited to add full code. Everything has been migrated to v4 but I'm just not sure about that section since layers is returning as an empty array. <body> <script src="http://d3js.org/d3.v4.js"></script> <div class="chart"> </div> <script> chart("data.json", "orange"); var datearray = []; var colorrange = []; function chart(jsonpath, color) { if (color == "blue") { colorrange = ["#045A8D", "#2B8CBE", "#74A9CF", "#A6BDDB", "#D0D1E6", "#F1EEF6"]; } else if (color == "pink") { colorrange = ["#980043", "#DD1C77", "#DF65B0", "#C994C7", "#D4B9DA", "#F1EEF6"]; } else if (color == "orange") { colorrange = ["#B30000", "#E34A33", "#FC8D59", "#FDBB84", "#FDD49E", "#FEF0D9"]; } strokecolor = colorrange[0]; var format = d3.timeFormat("%m/%d/%y"); var margin = {top: 20, right: 40, bottom: 30, left: 30}; var width = document.body.clientWidth - margin.left - margin.right; var height = 400 - margin.top - margin.bottom; var tooltip = d3.select("body") .append("div") .attr("class", "remove") .style("position", "absolute") .style("z-index", "20") .style("visibility", "hidden") .style("top", "30px") .style("left", "55px"); var x = d3.scaleTime() .range([0, width]); var y = d3.scaleLinear() .range([height-10, 0]); var z = d3.scaleOrdinal() .range(colorrange); var xAxis = d3.axisBottom() .scale(x) .tickFormat(d3.timeWeeks); var yAxis = d3.axisLeft() .scale(y); var yAxisr = d3.axisRight() .scale(y); var stack = d3.stack() .offset(d3.stackOffsetSilhouette) .value(function(d) { return d.values; }); var nest = d3.nest() .key(function(d) { return d.key; }); var area = d3.area() .curve(d3.curveCardinal) .x(function(d) { return x(d.date); }) .y0(function(d) { return y(d.y0); }) .y1(function(d) { return y(d.y0 + d.y); }); var svg = d3.select(".chart").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 graph = d3.json(jsonpath, function(data) { var parsed = []; var mainVal = []; for (var i = 0; i < data.length; i ++) { var timeData = JSON.parse(data[i]).default.timelineData; parsed.push(timeData); } for (var j = 0; j < parsed.length; j++) { for (var k = 0; k < parsed[j].length; k++) { obj = {}; var date = new Date(1000*parsed[j][k].time); obj.value = parsed[j][k].value[0]; obj.date = date; obj.key = 'arr' + j; mainVal.push(obj); } } mainVal.forEach(function(d) { d.date = d.date; d.value = +d.value; }); var layers = nest.entries(mainVal); x.domain(d3.extent(mainVal, function(d) { return d.date; })); y.domain([0, d3.max(mainVal, function(d) { return d.y0 + d.y; })]); svg.selectAll(".layer") .data(layers) .enter().append("path") .attr("class", "layer") .attr("d", function(d) { console.log(d.values); console.log(area(d.values)); return area(d.values); }) .style("fill", function(d, i) { return z(i); }); svg.append("g") .attr("class", "x axis") .attr("transform", "translate(0," + height + ")") .call(xAxis); svg.append("g") .attr("class", "y axis") .attr("transform", "translate(" + width + ", 0)") .call(yAxisr); svg.append("g") .attr("class", "y axis") .call(yAxis); svg.selectAll(".layer") .attr("opacity", 1) .on("mouseover", function(d, i) { svg.selectAll(".layer").transition() .duration(250) .attr("opacity", function(d, j) { return j != i ? 0.6 : 1; })}) .on("mousemove", function(d, i) { mousex = d3.mouse(this); mousex = mousex[0]; var invertedx = x.invert(mousex); invertedx = invertedx.getMonth() + invertedx.getDate(); var selected = (d.values); for (var k = 0; k < selected.length; k++) { datearray[k] = selected[k].date datearray[k] = datearray[k].getMonth() + datearray[k].getDate(); } mousedate = datearray.indexOf(invertedx); pro = d.values[mousedate].value; d3.select(this) .classed("hover", true) .attr("stroke", strokecolor) .attr("stroke-width", "0.5px"), tooltip.html( "<p>" + d.key + "<br>" + pro + "</p>" ).style("visibility", "visible"); }) .on("mouseout", function(d, i) { svg.selectAll(".layer") .transition() .duration(250) .attr("opacity", "1"); d3.select(this) .classed("hover", false) .attr("stroke-width", "0px"), tooltip.html( "<p>" + d.key + "<br>" + pro + "</p>" ).style("visibility", "hidden"); }) var vertical = d3.select(".chart") .append("div") .attr("class", "remove") .style("position", "absolute") .style("z-index", "19") .style("width", "1px") .style("height", "380px") .style("top", "10px") .style("bottom", "30px") .style("left", "0px") .style("background", "#fff"); d3.select(".chart") .on("mousemove", function(){ mousex = d3.mouse(this); mousex = mousex[0] + 5; vertical.style("left", mousex + "px" )}) .on("mouseover", function(){ mousex = d3.mouse(this); mousex = mousex[0] + 5; vertical.style("left", mousex + "px")}); }); } </script>
Update d3 chart
I'm plotting a graph with this code (based on this example): var colorrange = []; function chart(data, desc_colors) { strokecolor = "#045A8D"; var mapPlotHeight = parseInt(d3.select("#map").style("height")); var mapPlotHeight = parseInt(d3.select("#map").style("height")); var sidebarWidth = parseInt(d3.select("#sidebar").style("width")); var streamPlotMargin = {top: 20, right: 30, bottom: 30, left: 30}; var streamPlotWidth = document.body.clientWidth - streamPlotMargin.left - streamPlotMargin.right - sidebarWidth; var streamPlotHeight = 200 - streamPlotMargin.top - streamPlotMargin.bottom; var colorrange = []; for (key in desc_colors) { colorrange.push(desc_colors[key]); } var tooltip = d3.select("body") .append("div") .attr("class", "remove") .style("position", "absolute") .style("z-index", "20") .style("visibility", "hidden") .style("top", mapPlotHeight + 50 + streamPlotMargin.top + "px") // 50 of nav top .style("left", sidebarWidth + 80 + "px"); var x = d3.scale.linear() .range([0, streamPlotWidth]); var y = d3.scale.linear() .range([streamPlotHeight-10, 0]); var z = d3.scale.ordinal() .range(colorrange); var xAxis = d3.svg.axis() .scale(x) .orient("bottom") .ticks(24); var yAxis = d3.svg.axis() .scale(y); var yAxisr = d3.svg.axis() .scale(y); var stack = d3.layout.stack() .offset("silhouette") .values(function(d) { return d.values; }) .x(function(d) { return d.hour; }) .y(function(d) { return d.value; }); // Group by key var nest = d3.nest() .key(function(d) { return d.key; }) var area = d3.svg.area() .interpolate("cardinal") .x(function(d) { return x(d.hour); }) .y0(function(d) { return y(d.y0); }) .y1(function(d) { return y(d.y0 + d.y); }); var svg = d3.select(".chart").attr("align","center") .append("svg") .attr("width", streamPlotWidth + streamPlotMargin.right + streamPlotMargin.left) .attr("height", streamPlotHeight + streamPlotMargin.top + streamPlotMargin.bottom) .append("g") .attr("transform", "translate(" + streamPlotMargin.left + "," + streamPlotMargin.top + ")"); data.forEach(function(d) { d.hour = d.hour; d.value = +d.value; }); var layers = stack(nest.entries(data)); x.domain(d3.extent(data, function(d) { return d.hour; })); y.domain([0, d3.max(data, function(d) { return d.y0 + d.y; })]); svg.selectAll(".layer") .data(layers) .enter().append("path") .attr("class", "layer") .attr("d", function(d) { return area(d.values); }) .style("fill", function(d, i) { return z(i); }); svg.append("g") .attr("class", "x axis") .attr("transform", "translate(0," + streamPlotHeight + ")") .call(xAxis); svg.append("g") .attr("class", "y axis") .call(yAxis.orient("left")); svg.selectAll(".layer") .attr("opacity", 1) .on("mouseover", function(d, i) { svg.selectAll(".layer").transition() .duration(250) .attr("opacity", function(d, j) { return j != i ? 0.6 : 1; })}) .on("mousemove", function(d, i) { mousex = d3.mouse(this); mousex = mousex[0]; var invertedx = x.invert(mousex); console.log(invertedx); pro = d.values[Math.round(invertedx)].value; console.log(pro); d3.select(this) .classed("hover", true) .attr("stroke", strokecolor) .attr("stroke-width", "0.5px"), tooltip.html( "<p>" + d.key + "<br>" + pro + "</p>" ).style("visibility", "visible"); }) .on("mouseout", function(d, i) { svg.selectAll(".layer") .transition() .duration(250) .attr("opacity", "1"); d3.select(this) .classed("hover", false) .attr("stroke-width", "0px"), tooltip.html( "<p>" + d.key + "<br>" + pro + "</p>" ).style("visibility", "hidden"); }) var vertical = d3.select(".chart") .append("div") .attr("class", "remove") .style("position", "absolute") .style("z-index", "19") .style("width", "1px") .style("height", "200px") .style("top", mapPlotHeight + streamPlotMargin.bottom) .style("bottom", "0px") .style("left", "0px") .style("background", "#fff"); d3.select(".chart") .on("mousemove", function(){ mousex = d3.mouse(this); mousex = mousex[0] + 5; vertical.style("left", mousex + "px" )}) .on("mouseover", function(){ mousex = d3.mouse(this); mousex = mousex[0] + 5; vertical.style("left", mousex + "px")}); } That results in something similar to this: http://bl.ocks.org/WillTurman/raw/4631136/ However, I would like to update this chart based on a query. I found these to examples: http://bl.ocks.org/d3noob/7030f35b72de721622b8 http://bl.ocks.org/mbostock/4060954 But I don't know how to apply then to my code. I would like to do something different then having a function just for update a chart. I would like to, inside the chart() function, be able to check if a chart already exists. If so, I would just update it (data, x, y), using a transition.
I would like to do something different then having a function just for update a chart. I would like to, inside the chart() function, be able to check if a chart already exists. If you want to check if a chart already exists, you can first assign an id to that chart, and then check if something with that id already exists when you need to decide if you should update the chart or otherwise. Something like this var svg = d3.select(".chart").attr("align","center") .append("svg") .attr("id", "svg-elem") Then, use something along these lines to decide what to call next. if(!d3.select("#svg-elem").node()){ // chart doesn't yet exist. // call chart initilization code? } else { // call chart update code }
Hover d3.js Streamgraph
I am trying to fix a hover, tool tip problem on my stream graph. I have a data set of decades and immigration data. When I hover over the graph it only shows the data for one decade, but the entire graph shows all the data. I also am trying to correct axis labels. For instance, the data for Russia should be , at the highest point: 433,427 <script src="http://d3js.org/d3.v2.js"></script> <div class="chart"> </div> <script> chart("Data.csv", "blue"); var datearray = []; var colorrange = []; function chart(csvpath, color) { if (color == "blue") { colorrange = ["#045A8D", "#2B8CBE", "#74A9CF", "#A6BDDB", "#D0D1E6", "#F1EEF6"]; } else if (color == "pink") { colorrange = ["#980043", "#DD1C77", "#DF65B0", "#C994C7", "#D4B9DA", "#F1EEF6"]; } else if (color == "orange") { colorrange = ["#B30000", "#E34A33", "#FC8D59", "#FDBB84", "#FDD49E", "#FEF0D9"]; } strokecolor = colorrange[0]; var format = d3.time.format("%m/%d/%y"); var margin = {top: 20, right: 40, bottom: 30, left: 30}; var width = document.body.clientWidth - margin.left - margin.right; var height = 400 - margin.top - margin.bottom; var tooltip = d3.select("body") .append("div") .attr("class", "remove") .style("position", "absolute") .style("z-index", "20") .style("visibility", "hidden") .style("top", "30px") .style("left", "55px"); var x = d3.time.scale() .range([0, width]); var y = d3.scale.linear() .range([height-10, 0]); var z = d3.scale.ordinal() .range(colorrange); var xAxis = d3.svg.axis() .scale(x) .orient("bottom") .ticks(d3.time.years); var yAxis = d3.svg.axis() .scale(y); var yAxisr = d3.svg.axis() .scale(y); var stack = d3.layout.stack() .offset("silhouette") .values(function(d) { return d.values; }) .x(function(d) { return d.date; }) .y(function(d) { return d.value; }); var nest = d3.nest() .key(function(d) { return d.key; }); var area = d3.svg.area() .interpolate("cardinal") .x(function(d) { return x(d.date); }) .y0(function(d) { return y(d.y0); }) .y1(function(d) { return y(d.y0 + d.y); }); var svg = d3.select(".chart").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 + ")"); /* correct this function var graph = d3.csv(csvpath, function(data) { data.forEach(function(d) { d.date = format.parse(d.date); d.value = +d.value; });*/ var graph = d3.csv(csvpath, function(raw) { var data = []; raw.forEach(function (d) { data.push({ key: d.Country, date : new Date(1980), value : parseInt(d['1980-1989'].replace(',','')) //get rid of the thousand separator }); data.push({ key: d.Country, date : new Date(1990), value : parseInt(d['1990-1999'].replace(',','')) }); data.push({ key: d.Country, date : new Date(2000), value : parseInt(d['2000-2009'].replace(',','') ) }); }); var layers = stack(nest.entries(data)); x.domain(d3.extent(data, function(d) { return d.date; })); y.domain([0, d3.max(data, function(d) { return d.y0 + d.y; })]); svg.selectAll(".layer") .data(layers) .enter().append("path") .attr("class", "layer") .attr("d", function(d) { return area(d.values); }) .style("fill", function(d, i) { return z(i); }); svg.append("g") .attr("class", "x axis") .attr("transform", "translate(0," + height + ")") .call(xAxis); svg.append("g") .attr("class", "y axis") .attr("transform", "translate(" + width + ", 0)") .call(yAxis.orient("right")); svg.append("g") .attr("class", "y axis") .call(yAxis.orient("left")); svg.selectAll(".layer") .attr("opacity", 1) .on("mouseover", function(d, i) { svg.selectAll(".layer").transition() .duration(250) .attr("opacity", function(d, j) { return j != i ? 0.6 : 1; })}) .on("mousemove", function(d, i) { mousex = d3.mouse(this); mousex = mousex[0]; var invertedx = x.invert(mousex); invertedx = invertedx.getMonth() + invertedx.getDate(); var selected = (d.values); for (var k = 0; k < selected.length; k++) { datearray[k] = selected[k].date datearray[k] = datearray[k].getMonth() + datearray[k].getDate(); } mousedate = datearray.indexOf(invertedx); pro = d.values[mousedate].value; d3.select(this) .classed("hover", true) .attr("stroke", strokecolor) .attr("stroke-width", "0.5px"), tooltip.html( "<p>" + d.key + "<br>" + pro + "</p>" ).style("visibility", "visible"); }) .on("mouseout", function(d, i) { svg.selectAll(".layer") .transition() .duration(250) .attr("opacity", "1"); d3.select(this) .classed("hover", false) .attr("stroke-width", "0px"), tooltip.html( "<p>" + d.key + "<br>" + pro + "</p>" ).style("visibility", "hidden"); }) var vertical = d3.select(".chart") .append("div") .attr("class", "remove") .style("position", "absolute") .style("z-index", "19") .style("width", "1px") .style("height", "380px") .style("top", "10px") .style("bottom", "30px") .style("left", "0px") .style("background", "#fff"); d3.select(".chart") .on("mousemove", function(){ mousex = d3.mouse(this); mousex = mousex[0] + 5; vertical.style("left", mousex + "px" )}) .on("mouseover", function(){ mousex = d3.mouse(this); mousex = mousex[0] + 5; vertical.style("left", mousex + "px")}); }); } </script> I am adapting the code from this post: http://bl.ocks.org/WillTurman/4631136 My data would be per decade so 1980-1989,1990-1999, 2000-2009 1980-1989 1990-1999 2000-2009 i.e, Russia 33,311 433,427 167,152