var w = 960, h = 500, x = d3.scale.linear().range([0, w]), y = d3.scale.linear().range([0, h - 40]); // An SVG element with a bottom-right origin. var svg = d3.select("#chart").append("svg:svg") .attr("width", w) .attr("height", h) .style("padding-right", "30px") .append("svg:g") .attr("transform", "translate(" + x(1) + "," + (h - 20) + ")scale(-1,-1)"); // A sliding container to hold the bars. var body = svg.append("svg:g") .attr("transform", "translate(0,0)"); // A container to hold the y-axis rules. var rules = svg.append("svg:g"); // A label for the current year. var title = svg.append("svg:text") .attr("class", "title") .attr("dy", ".71em") .attr("transform", "translate(" + x(1) + "," + y(1) + ")scale(-1,-1)") .text(2000); d3.csv("population.csv", function(data) { // Convert strings to numbers. data.forEach(function(d) { d.people = +d.people; d.year = +d.year; d.age = +d.age; }); // Compute the extent of the data set in age and years. var age0 = 0, age1 = d3.max(data, function(d) { return d.age; }), year0 = d3.min(data, function(d) { return d.year; }), year1 = d3.max(data, function(d) { return d.year; }), year = year1; // Update the scale domains. x.domain([0, age1 + 5]); y.domain([0, d3.max(data, function(d) { return d.people; })]); // Add rules to show the population values. rules = rules.selectAll(".rule") .data(y.ticks(10)) .enter().append("svg:g") .attr("class", "rule") .attr("transform", function(d) { return "translate(0," + y(d) + ")"; }); rules.append("svg:line") .attr("x2", w); rules.append("svg:text") .attr("x", 6) .attr("dy", ".35em") .attr("transform", "rotate(180)") .text(function(d) { return Math.round(d / 1e6) + "M"; }); // Add labeled rects for each birthyear. var years = body.selectAll("g") .data(d3.range(year0 - age1, year1 + 5, 5)) .enter().append("svg:g") .attr("transform", function(d) { return "translate(" + x(year1 - d) + ",0)"; }); years.selectAll("rect") .data(d3.range(2)) .enter().append("svg:rect") .attr("x", 1) .attr("width", x(5) - 2) .attr("height", 1e-6); years.append("svg:text") .attr("y", -6) .attr("x", -x(5) / 2) .attr("transform", "rotate(180)") .attr("text-anchor", "middle") .style("fill", "#fff") .text(String); // Add labels to show the age. svg.append("svg:g").selectAll("text") .data(d3.range(0, age1 + 5, 5)) .enter().append("svg:text") .attr("text-anchor", "middle") .attr("transform", function(d) { return "translate(" + (x(d) + x(5) / 2) + ",-4)scale(-1,-1)"; }) .attr("dy", ".71em") .text(String); // Nest by year then birthyear. data = d3.nest() .key(function(d) { return d.year; }) .key(function(d) { return d.year - d.age; }) .rollup(function(v) { return v.map(function(d) { return d.people; }); }) .map(data); // Allow the arrow keys to change the displayed year. d3.select(window).on("keydown", function() { switch (d3.event.keyCode) { case 37: year = Math.max(year0, year - 10); break; case 39: year = Math.min(year1, year + 10); break; } redraw(); }); redraw(); function redraw() { if (!(year in data)) return; title.text(year); body.transition() .duration(750) .attr("transform", function(d) { return "translate(" + x(year - year1) + ",0)"; }); years.selectAll("rect") .data(function(d) { return data[year][d] || [0, 0]; }) .transition() .duration(750) .attr("height", y); } });