Radial bar chart inspired by Peter Cook's work.
forked from bricedev's block: Radial Bar Chart
| license: mit |
Radial bar chart inspired by Peter Cook's work.
forked from bricedev's block: Radial Bar Chart
| name | value | |
|---|---|---|
| Everyday Spending | 2 | |
| Savings | 1 | |
| Investments | 0 | |
| Pensions | 2 | |
| Property | 3 |
| <!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 = 500, | |
| height = 500, | |
| barHeight = height / 2 - 40; | |
| var formatNumber = d3.format("s"); | |
| var color = d3.scale.ordinal() | |
| .domain([1, 2, 3]) | |
| .range(["#C50000","#F9B001","#4CC500"]); | |
| var svg = d3.select('body').append("svg") | |
| .attr("width", width) | |
| .attr("height", height) | |
| .append("g") | |
| .attr("transform", "translate(" + width/2 + "," + height/2 + ")"); | |
| d3.csv("data.csv", function(error, data) { | |
| var extent = d3.extent(data, function(d) { return d.value; }); | |
| var barScale = d3.scale.linear() | |
| .domain(extent) | |
| .range([0, barHeight]); | |
| var keys = data.map(function(d,i) { return d.name; }); | |
| var numBars = keys.length; | |
| var x = d3.scale.linear() | |
| .domain(extent) | |
| .range([0, -barHeight]); | |
| var xAxis = d3.svg.axis() | |
| .scale(x).orient("left") | |
| .ticks(3) | |
| .tickFormat(formatNumber); | |
| var circles = svg.selectAll("circle") | |
| .data(x.ticks(3)) | |
| .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 arc = d3.svg.arc() | |
| .startAngle(function(d,i) { return (i * 2 * Math.PI) / numBars; }) | |
| .endAngle(function(d,i) { return ((i + 1) * 2 * Math.PI) / numBars; }) | |
| .innerRadius(0); | |
| var segments = svg.selectAll("path") | |
| .data(data) | |
| .enter().append("path") | |
| .each(function(d) { d.outerRadius = 0; }) | |
| .style("fill", function (d) { return color(d.value); }) | |
| .attr("d", arc); | |
| segments.transition().ease("elastic").duration(800).delay(function(d,i) {return (5-i)*100;}) | |
| .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"); | |
| var lines = svg.selectAll("line") | |
| .data(keys) | |
| .enter().append("line") | |
| .attr("y2", -barHeight - 20) | |
| .style("stroke", "black") | |
| .style("stroke-width",".5px") | |
| .attr("transform", function(d, i) { return "rotate(" + (i * 360 / numBars) + ")"; }); | |
| // 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(keys) | |
| .enter().append("text") | |
| .style("text-anchor", "middle") | |
| .style("font-size","15px") | |
| .style("fill", function(d, i) {return "#3e3e3e";}) | |
| .append("textPath") | |
| .attr("xlink:href", "#label-path") | |
| .attr("startOffset", function(d, i) {return i * 100 / numBars + 50 / numBars + '%';}) | |
| .text(function(d) {return d.toUpperCase(); }); | |
| }); | |
| </script> |