2010-09-28 22:34:52 +04:00
|
|
|
<html>
|
|
|
|
<head>
|
|
|
|
<title>Donut Chart</title>
|
|
|
|
<script type="text/javascript" src="../../d3.js"></script>
|
|
|
|
<style type="text/css">
|
|
|
|
|
|
|
|
body {
|
|
|
|
font: 10px sans-serif;
|
|
|
|
}
|
|
|
|
|
|
|
|
</style>
|
|
|
|
</head>
|
|
|
|
<body>
|
|
|
|
<script type="text/javascript">
|
|
|
|
|
|
|
|
var w = 400,
|
|
|
|
h = 400,
|
|
|
|
r = Math.min(w, h) / 2,
|
2010-10-25 03:15:43 +04:00
|
|
|
n = 10,
|
|
|
|
data = normalize(d3.range(n).map(Math.random)),
|
|
|
|
color = d3.category20();
|
2010-09-28 22:34:52 +04:00
|
|
|
|
|
|
|
var vis = d3.select("body")
|
2010-10-02 22:00:31 +04:00
|
|
|
.append("svg:svg")
|
2010-09-28 22:34:52 +04:00
|
|
|
.attr("width", w)
|
|
|
|
.attr("height", h);
|
|
|
|
|
|
|
|
var arcs = vis.selectAll("g.arc")
|
|
|
|
.data(data)
|
2010-10-24 21:39:34 +04:00
|
|
|
.enter("svg:g")
|
2010-09-28 22:34:52 +04:00
|
|
|
.attr("class", "arc")
|
|
|
|
.attr("transform", "translate(" + r + "," + r + ")");
|
|
|
|
|
2010-10-02 22:00:31 +04:00
|
|
|
arcs.append("svg:path")
|
2010-10-25 03:15:43 +04:00
|
|
|
.attr("fill", function(d, i) { return color(i); })
|
2010-09-28 22:34:52 +04:00
|
|
|
.attr("d", arc);
|
|
|
|
|
2010-10-24 21:39:34 +04:00
|
|
|
window.addEventListener("keypress", update, false);
|
|
|
|
|
|
|
|
function update() {
|
|
|
|
var prev = data,
|
|
|
|
next = data = normalize(d3.range(n).map(Math.random)),
|
|
|
|
i = 0;
|
|
|
|
for (; i < n; ++i) prev[i].next = next[i];
|
|
|
|
d3.selectAll("g.arc > path")
|
|
|
|
.data(prev)
|
|
|
|
.each(transitionSplit);
|
|
|
|
}
|
|
|
|
|
|
|
|
// 1. Wedges split into two rings.
|
|
|
|
function transitionSplit(d, i) {
|
|
|
|
d3.select(this)
|
|
|
|
.transition()
|
2010-10-24 23:13:15 +04:00
|
|
|
.attrTween("d", tweenArc({
|
2010-10-24 21:39:34 +04:00
|
|
|
innerRadius: i & 1 ? r * .6 : r * .8,
|
|
|
|
outerRadius: i & 1 ? r * .8 : r
|
|
|
|
}))
|
2010-10-24 23:13:15 +04:00
|
|
|
.each("end", transitionRotate);
|
2010-10-24 21:39:34 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
// 2. Wedges translate to be centered on their final position.
|
|
|
|
function transitionRotate(d, i) {
|
|
|
|
var a0 = d.next.startAngle + d.next.endAngle,
|
|
|
|
a1 = d.startAngle - d.endAngle;
|
|
|
|
d3.select(this)
|
|
|
|
.transition()
|
2010-10-24 23:13:15 +04:00
|
|
|
.attrTween("d", tweenArc({
|
2010-10-24 21:39:34 +04:00
|
|
|
startAngle: (a0 + a1) / 2,
|
|
|
|
endAngle: (a0 - a1) / 2
|
|
|
|
}))
|
2010-10-24 23:13:15 +04:00
|
|
|
.each("end", transitionResize);
|
2010-10-24 21:39:34 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
// 3. Wedges then update their values, changing size.
|
|
|
|
function transitionResize(d, i) {
|
|
|
|
d3.select(this)
|
|
|
|
.transition()
|
2010-10-24 23:13:15 +04:00
|
|
|
.attrTween("d", tweenArc({
|
2010-09-28 22:34:52 +04:00
|
|
|
startAngle: d.next.startAngle,
|
|
|
|
endAngle: d.next.endAngle
|
2010-10-24 21:39:34 +04:00
|
|
|
}))
|
2010-10-24 23:13:15 +04:00
|
|
|
.each("end", transitionUnite);
|
2010-10-24 21:39:34 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
// 4. Wedges reunite into a single ring.
|
|
|
|
function transitionUnite(d, i) {
|
|
|
|
d3.select(this)
|
|
|
|
.transition()
|
2010-10-24 23:13:15 +04:00
|
|
|
.attrTween("d", tweenArc({
|
2010-09-28 22:34:52 +04:00
|
|
|
innerRadius: d.next.innerRadius,
|
|
|
|
outerRadius: d.next.outerRadius
|
2010-10-24 21:39:34 +04:00
|
|
|
}));
|
|
|
|
}
|
2010-09-28 22:34:52 +04:00
|
|
|
|
2010-10-24 23:13:15 +04:00
|
|
|
function tweenArc(b) {
|
2010-10-24 21:39:34 +04:00
|
|
|
return function(a) {
|
2010-10-24 23:13:15 +04:00
|
|
|
var i = d3.interpolate(a, b);
|
2010-10-24 21:39:34 +04:00
|
|
|
for (var key in b) a[key] = b[key]; // update data
|
|
|
|
return function(t) {
|
|
|
|
return arc(i(t));
|
|
|
|
};
|
|
|
|
};
|
2010-09-28 22:34:52 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
function normalize(array) {
|
|
|
|
var k = (2 * Math.PI) / array.reduce(function(p, d) { return p + d; }, 0),
|
|
|
|
a = 0;
|
|
|
|
return array.map(function(d, i) {
|
|
|
|
return {
|
|
|
|
innerRadius: r * .6,
|
|
|
|
outerRadius: r,
|
|
|
|
startAngle: a,
|
|
|
|
endAngle: a += d * k
|
|
|
|
};
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
function arc(d) {
|
|
|
|
var r0 = d.innerRadius,
|
|
|
|
r1 = d.outerRadius,
|
|
|
|
a0 = d.startAngle - Math.PI / 2,
|
|
|
|
a1 = d.endAngle - Math.PI / 2,
|
|
|
|
da = a1 - a0,
|
|
|
|
c0 = Math.cos(a0),
|
|
|
|
s0 = Math.sin(a0),
|
|
|
|
c1 = Math.cos(a1),
|
|
|
|
s1 = Math.sin(a1);
|
|
|
|
return "M" + r1 * c0 + "," + r1 * s0
|
|
|
|
+ "A" + r1 + "," + r1 + " 0 "
|
|
|
|
+ ((da < Math.PI) ? "0" : "1") + ",1 "
|
|
|
|
+ r1 * c1 + "," + r1 * s1
|
|
|
|
+ "L" + r0 * c1 + "," + r0 * s1
|
|
|
|
+ "A" + r0 + "," + r0 + " 0 "
|
|
|
|
+ ((da < Math.PI) ? "0" : "1") + ",0 "
|
|
|
|
+ r0 * c0 + "," + r0 * s0 + "Z";
|
|
|
|
}
|
|
|
|
|
|
|
|
</script>
|
|
|
|
</body>
|
|
|
|
</html>
|