A radial, fancy and almost unreadable version of the classic Grouped Bar Chart from mbostock.
forked from bricedev's block: Grouped Radial Bar Chart
| license: mit |
A radial, fancy and almost unreadable version of the classic Grouped Bar Chart from mbostock.
forked from bricedev's block: Grouped Radial Bar Chart
| [ | |
| { | |
| "State": "CA", | |
| "ages": [ | |
| { | |
| "name": "Under 5 Years", | |
| "value": 2704659 | |
| }, | |
| { | |
| "name": "5 to 13 Years", | |
| "value": 4499890 | |
| }, | |
| { | |
| "name": "14 to 17 Years", | |
| "value": 2159981 | |
| }, | |
| { | |
| "name": "18 to 24 Years", | |
| "value": 3853788 | |
| }, | |
| { | |
| "name": "25 to 44 Years", | |
| "value": 10604510 | |
| }, | |
| { | |
| "name": "45 to 64 Years", | |
| "value": 8819342 | |
| }, | |
| { | |
| "name": "65 Years and Over", | |
| "value": 4114496 | |
| } | |
| ] | |
| }, | |
| { | |
| "State": "TX", | |
| "ages": [ | |
| { | |
| "name": "Under 5 Years", | |
| "value": 2027307 | |
| }, | |
| { | |
| "name": "5 to 13 Years", | |
| "value": 3277946 | |
| }, | |
| { | |
| "name": "14 to 17 Years", | |
| "value": 1420518 | |
| }, | |
| { | |
| "name": "18 to 24 Years", | |
| "value": 2454721 | |
| }, | |
| { | |
| "name": "25 to 44 Years", | |
| "value": 7017731 | |
| }, | |
| { | |
| "name": "45 to 64 Years", | |
| "value": 5656528 | |
| }, | |
| { | |
| "name": "65 Years and Over", | |
| "value": 2472223 | |
| } | |
| ] | |
| }, | |
| { | |
| "State": "NY", | |
| "ages": [ | |
| { | |
| "name": "Under 5 Years", | |
| "value": 1208495 | |
| }, | |
| { | |
| "name": "5 to 13 Years", | |
| "value": 2141490 | |
| }, | |
| { | |
| "name": "14 to 17 Years", | |
| "value": 1058031 | |
| }, | |
| { | |
| "name": "18 to 24 Years", | |
| "value": 1999120 | |
| }, | |
| { | |
| "name": "25 to 44 Years", | |
| "value": 5355235 | |
| }, | |
| { | |
| "name": "45 to 64 Years", | |
| "value": 5120254 | |
| }, | |
| { | |
| "name": "65 Years and Over", | |
| "value": 2607672 | |
| } | |
| ] | |
| }, | |
| { | |
| "State": "FL", | |
| "ages": [ | |
| { | |
| "name": "Under 5 Years", | |
| "value": 1140516 | |
| }, | |
| { | |
| "name": "5 to 13 Years", | |
| "value": 1938695 | |
| }, | |
| { | |
| "name": "14 to 17 Years", | |
| "value": 925060 | |
| }, | |
| { | |
| "name": "18 to 24 Years", | |
| "value": 1607297 | |
| }, | |
| { | |
| "name": "25 to 44 Years", | |
| "value": 4782119 | |
| }, | |
| { | |
| "name": "45 to 64 Years", | |
| "value": 4746856 | |
| }, | |
| { | |
| "name": "65 Years and Over", | |
| "value": 3187797 | |
| } | |
| ] | |
| }, | |
| { | |
| "State": "IL", | |
| "ages": [ | |
| { | |
| "name": "Under 5 Years", | |
| "value": 894368 | |
| }, | |
| { | |
| "name": "5 to 13 Years", | |
| "value": 1558919 | |
| }, | |
| { | |
| "name": "14 to 17 Years", | |
| "value": 725973 | |
| }, | |
| { | |
| "name": "18 to 24 Years", | |
| "value": 1311479 | |
| }, | |
| { | |
| "name": "25 to 44 Years", | |
| "value": 3596343 | |
| }, | |
| { | |
| "name": "45 to 64 Years", | |
| "value": 3239173 | |
| }, | |
| { | |
| "name": "65 Years and Over", | |
| "value": 1575308 | |
| } | |
| ] | |
| }, | |
| { | |
| "State": "PA", | |
| "ages": [ | |
| { | |
| "name": "Under 5 Years", | |
| "value": 737462 | |
| }, | |
| { | |
| "name": "5 to 13 Years", | |
| "value": 1345341 | |
| }, | |
| { | |
| "name": "14 to 17 Years", | |
| "value": 679201 | |
| }, | |
| { | |
| "name": "18 to 24 Years", | |
| "value": 1203944 | |
| }, | |
| { | |
| "name": "25 to 44 Years", | |
| "value": 3157759 | |
| }, | |
| { | |
| "name": "45 to 64 Years", | |
| "value": 3414001 | |
| }, | |
| { | |
| "name": "65 Years and Over", | |
| "value": 1910571 | |
| } | |
| ] | |
| } | |
| ] |
| <!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; | |
| } | |
| </style> | |
| <body> | |
| <script src="https://d3js.org/d3.v3.min.js"></script> | |
| <script> | |
| var width = 960, | |
| height = 700, | |
| barHeight = height / 2 - 40; | |
| var formatNumber = d3.format("s"); | |
| var color = d3.scale.ordinal() | |
| .range(["#98abc5", "#8a89a6", "#7b6888", "#6b486b", "#a05d56", "#d0743c", "#ff8c00"]); | |
| var svg = d3.select('body').append("svg") | |
| .attr("width", width) | |
| .attr("height", height) | |
| .append("g") | |
| .attr("transform", "translate(" + width/2 + "," + height/2 + ")"); | |
| d3.json("data.json", function(error, data) { | |
| var statesNames = data.map(function(d) { return d.State; }); | |
| var ageNames = data[0].ages.map(function(d) { return d.name; }); | |
| var barScale = d3.scale.linear() | |
| .domain([0, d3.max(data, function(d) { return d3.max(d.ages, function(d) { return d.value; }); })]) | |
| .range([0, barHeight]); | |
| var numBarsStates = statesNames.length ; | |
| var numBarsAges = ageNames.length ; | |
| var x = d3.scale.linear() | |
| .domain([0, d3.max(data, function(d) { return d3.max(d.ages, function(d) { return d.value; }); })]) | |
| .range([0, -barHeight]); | |
| var xAxis = d3.svg.axis() | |
| .scale(x).orient("left") | |
| .ticks(5) | |
| .tickFormat(formatNumber); | |
| var circles = svg.selectAll("circle") | |
| .data(x.ticks(5)) | |
| .enter().append("circle") | |
| .attr("r", function(d) {return barScale(d);}) | |
| .style("fill", "none") | |
| .style("stroke", "black") | |
| .style("stroke-dasharray", "2,2") | |
| .style("stroke-width",".5px"); | |
| var states = svg.selectAll(".state") | |
| .data(data) | |
| .enter().append("g") | |
| .attr("class", "state") | |
| .attr("transform", function(d,i) { return "rotate(" + (i * 360 / numBarsStates) + ")"; }); | |
| var arc = d3.svg.arc() | |
| .startAngle(function(d,i) { return (i * 2 * Math.PI) / (numBarsAges*numBarsStates); }) | |
| .endAngle(function(d,i) { return ((i + 1) * 2 * Math.PI) / (numBarsAges*numBarsStates); }) | |
| .innerRadius(0); | |
| var segments = states.selectAll("path") | |
| .data(function(d) { return d.ages; }) | |
| .enter().append("path") | |
| .each(function(d) { d.outerRadius = 0; }) | |
| .style("fill", function (d) { return color(d.name); }) | |
| .attr("d", arc); | |
| segments.transition().ease("elastic").duration(1200).delay(function(d,i,u) { return u * 200 + 400;}) | |
| .attrTween("d", function(d,index) { | |
| var i = d3.interpolate(d.outerRadius, barScale(d.value)); | |
| return function(t) { d.outerRadius = i(t); return arc(d,index); }; | |
| }); | |
| svg.append("circle") | |
| .attr("r", barHeight) | |
| .classed("outer", true) | |
| .style("fill", "none") | |
| .style("stroke", "black") | |
| .style("stroke-width","1.5px"); | |
| states.selectAll("line") | |
| .data(function(d) { return d.ages; }) | |
| .enter().append("line") | |
| .attr("y2", function(d,i) { return i===0 ? -barHeight - 20 : -barHeight; }) | |
| .style("stroke", "black") | |
| .style("stroke-width", function(d,i) { return i===0 ? "1px" : "0.2px"; }) | |
| .attr("transform", function(d, i) { return "rotate(" + (i * 360 / (numBarsAges*numBarsStates)) + ")"; }); | |
| svg.append("g") | |
| .attr("class", "x axis") | |
| .call(xAxis); | |
| // Labels | |
| var labelRadius = barHeight * 1.025; | |
| var labels = svg.append("g") | |
| .classed("labels", true); | |
| labels.append("def") | |
| .append("path") | |
| .attr("id", "label-path") | |
| .attr("d", "m0 " + -labelRadius + " a" + labelRadius + " " + labelRadius + " 0 1,1 -0.01 0"); | |
| labels.selectAll("text") | |
| .data(statesNames) | |
| .enter().append("text") | |
| .style("text-anchor", "middle") | |
| .style("font-weight","bold") | |
| .style("fill", function(d, i) {return "#3e3e3e";}) | |
| .append("textPath") | |
| .attr("xlink:href", "#label-path") | |
| .attr("startOffset", function(d, i) {return i * 100 / numBarsStates + 50 / numBarsStates + '%';}) | |
| .text(function(d) {return d.toUpperCase(); }); | |
| // legend | |
| var legend = svg.selectAll(".legend") | |
| .data(ageNames.slice().reverse()) | |
| .enter().append("g") | |
| .attr("class", "legend") | |
| .attr("transform", function(d, i) { return "translate("+ -width/2 + "," + (-(height/2 - 20) + (i * 20)) + ")"; }); | |
| legend.append("rect") | |
| .attr("x", width - 33) | |
| .attr("width", 18) | |
| .attr("height", 18) | |
| .style("fill", color); | |
| legend.append("text") | |
| .attr("x", width - 39) | |
| .attr("y", 9) | |
| .attr("dy", ".35em") | |
| .style("text-anchor", "end") | |
| .text(function(d) { return d; }); | |
| }); | |
| d3.select(self.frameElement).style("height", height + "px"); | |
| </script> |