I'm continuting mbostocks's series of gists about pie charts.
Building on the previous version, this variation of a donut chart demonstrates a nice transition when the pie chart is drawn for the first time.
I'm continuting mbostocks's series of gists about pie charts.
Building on the previous version, this variation of a donut chart demonstrates a nice transition when the pie chart is drawn for the first time.
| <!DOCTYPE html> | |
| <meta charset="utf-8"> | |
| <style> | |
| body { | |
| font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; | |
| margin: auto; | |
| position: relative; | |
| width: 960px; | |
| } | |
| text { | |
| font: 10px sans-serif; | |
| } | |
| form { | |
| position: absolute; | |
| right: 10px; | |
| top: 10px; | |
| } | |
| </style> | |
| <form> | |
| <label><input type="radio" name="dataset" value="apples" checked> Apples</label> | |
| <label><input type="radio" name="dataset" value="oranges"> Oranges</label> | |
| </form> | |
| <script src="http://d3js.org/d3.v3.min.js"></script> | |
| <script> | |
| var dataset = { | |
| apples: [53245, 28479, 19697, 24037, 40245], | |
| oranges: [200, 200, 200, 200] | |
| }; | |
| var width = 960, | |
| height = 500, | |
| radius = Math.min(width, height) / 2; | |
| var enterClockwise = { | |
| startAngle: 0, | |
| endAngle: 0 | |
| }; | |
| var enterAntiClockwise = { | |
| startAngle: Math.PI * 2, | |
| endAngle: Math.PI * 2 | |
| }; | |
| var color = d3.scale.category20(); | |
| var pie = d3.layout.pie() | |
| .sort(null); | |
| var arc = d3.svg.arc() | |
| .innerRadius(radius - 100) | |
| .outerRadius(radius - 20); | |
| var svg = d3.select("body").append("svg") | |
| .attr("width", width) | |
| .attr("height", height) | |
| .append("g") | |
| .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")"); | |
| // set the start and end angles to 0 so we can transition | |
| // clockwise to the actual values later | |
| var path = svg.selectAll("path") | |
| .data(pie(dataset.apples)) | |
| .enter().append("path") | |
| .attr("fill", function(d, i) { return color(i); }) | |
| .attr("d", arc(enterClockwise)) | |
| .each(function(d) { | |
| this._current = { | |
| data: d.data, | |
| value: d.value, | |
| startAngle: enterClockwise.startAngle, | |
| endAngle: enterClockwise.endAngle | |
| } | |
| }); // store the initial values | |
| path.transition() // update | |
| .duration(750) | |
| .attrTween("d", arcTween); | |
| d3.selectAll("input").on("change", change); | |
| var timeout = setTimeout(function() { | |
| d3.select("input[value=\"oranges\"]").property("checked", true).each(change); | |
| }, 2000); | |
| function change() { | |
| clearTimeout(timeout); | |
| path = path.data(pie(dataset[this.value])); // update the data | |
| // set the start and end angles to Math.PI * 2 so we can transition | |
| // anticlockwise to the actual values later | |
| path.enter().append("path") | |
| .attr("fill", function (d, i) { | |
| return color(i); | |
| }) | |
| .attr("d", arc(enterAntiClockwise)) | |
| .each(function (d) { | |
| this._current = { | |
| data: d.data, | |
| value: d.value, | |
| startAngle: enterAntiClockwise.startAngle, | |
| endAngle: enterAntiClockwise.endAngle | |
| }; | |
| }); // store the initial values | |
| path.exit() | |
| .transition() | |
| .duration(750) | |
| .attrTween('d', arcTweenOut) | |
| .remove() // now remove the exiting arcs | |
| path.transition().duration(750).attrTween("d", arcTween); // redraw the arcs | |
| } | |
| // Store the displayed angles in _current. | |
| // Then, interpolate from _current to the new angles. | |
| // During the transition, _current is updated in-place by d3.interpolate. | |
| function arcTween(a) { | |
| var i = d3.interpolate(this._current, a); | |
| this._current = i(0); | |
| return function(t) { | |
| return arc(i(t)); | |
| }; | |
| } | |
| function arcTweenOut(a) { | |
| var i = d3.interpolate(this._current, {startAngle: Math.PI * 2, endAngle: Math.PI * 2, value: 0}); | |
| this._current = i(0); | |
| return function (t) { | |
| return arc(i(t)); | |
| }; | |
| } | |
| </script> |