This variation of a donut chart demonstrates how to update values with an animated transition. Clicking on the radio buttons changes the displayed metric.
Next: Missing Data
Previous: Static Update
license: gpl-3.0 |
This variation of a donut chart demonstrates how to update values with an animated transition. Clicking on the radio buttons changes the displayed metric.
Next: Missing Data
Previous: Static Update
apples | oranges | |
---|---|---|
53245 | 200 | |
28479 | 200 | |
19697 | 200 | |
24037 | 200 | |
40245 | 200 |
<!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="//d3js.org/d3.v3.min.js"></script> | |
<script> | |
var width = 960, | |
height = 500, | |
radius = Math.min(width, height) / 2; | |
var color = d3.scale.category20(); | |
var pie = d3.layout.pie() | |
.value(function(d) { return d.apples; }) | |
.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 + ")"); | |
d3.tsv("data.tsv", type, function(error, data) { | |
if (error) throw error; | |
var path = svg.datum(data).selectAll("path") | |
.data(pie) | |
.enter().append("path") | |
.attr("fill", function(d, i) { return color(i); }) | |
.attr("d", arc) | |
.each(function(d) { this._current = d; }); // store the initial angles | |
d3.selectAll("input") | |
.on("change", change); | |
var timeout = setTimeout(function() { | |
d3.select("input[value=\"oranges\"]").property("checked", true).each(change); | |
}, 2000); | |
function change() { | |
var value = this.value; | |
clearTimeout(timeout); | |
pie.value(function(d) { return d[value]; }); // change the value function | |
path = path.data(pie); // compute the new angles | |
path.transition().duration(750).attrTween("d", arcTween); // redraw the arcs | |
} | |
}); | |
function type(d) { | |
d.apples = +d.apples; | |
d.oranges = +d.oranges; | |
return d; | |
} | |
// 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)); | |
}; | |
} | |
</script> |
@evaughen Visualizing an all-zero dataset with a pie or donut chart won’t work very well.
I hope some day soon the code for D3 will seem less like magic and more like logic. I'll just to deal with the all zero dataset before it reaches the interpolate stage. Thanks for all your hard work...
function arcTween(a) {
var i = d3.interpolate(this._current, a);
/*
* I think, that it makes sense to change to this._current = i(1) to store latest transition, it works now, because of
* references. Change this._current = jQuery(this, {}, i(0)); will break animation.
*/
this._current = i(0);
return function(t) {
return arc(i(t));
};
}
Here's a jsbin version: http://jsbin.com/hegob/1/edit?js,output
Shouldn't line 85 read this._current = i(1);
to set the value for the next update? I don't see how "_current is updated in-place by d3.interpolate".
how would you handle transition between these two datasets...
data1 = [53245, 28479, 19697, 24037, 40245]
data2 = [0, 0, 0, 0, 0]
Transitioning between data1 to data2 works but transitioning back to data1 generates parsing errors.