2010-09-28 22:34:52 +04:00
|
|
|
<html>
|
|
|
|
<head>
|
|
|
|
<title>Donut Chart</title>
|
Simplify data join. Add insert & empty.
The data join is now specified as a single function of data, as with all other
properties. This allows the key to be computed on the previously-bound data,
rather than requiring the key to be serialized into the DOM (say, as an
attribute). In the case that there is no previously-bound data, it is still
possible to access the associated node as the `this` context.
The `enter` operator no longer performs an append. For symmetry with the `exit`
operator, you must call `append` after obtaining the entering selection. This
requires a tiny bit more code, but should make the code more clear. Also, it
provides an opportunity to use a different instantiation operator, such as the
new `insert` operator. This takes a second argument, which is a selector for the
insert-before reference element. For example, the selector ":first-child" will
prepend nodes.
The `empty` operator allows you to query whether a selection is empty (i.e.,
contains zero matching nodes).
2011-01-31 22:00:35 +03:00
|
|
|
<script type="text/javascript" src="../../d3.js"></script>
|
2010-09-28 22:34:52 +04:00
|
|
|
<style type="text/css">
|
|
|
|
|
|
|
|
body {
|
|
|
|
font: 10px sans-serif;
|
|
|
|
}
|
|
|
|
|
|
|
|
</style>
|
|
|
|
</head>
|
|
|
|
<body>
|
|
|
|
<script type="text/javascript">
|
|
|
|
|
|
|
|
var w = 400,
|
|
|
|
h = 400,
|
2010-10-25 04:05:59 +04:00
|
|
|
r1 = Math.min(w, h) / 2,
|
|
|
|
r0 = r1 * .6,
|
2010-10-25 03:15:43 +04:00
|
|
|
n = 10,
|
2010-10-25 04:05:59 +04:00
|
|
|
data = arcs(d3.range(n).map(Math.random)),
|
2010-10-31 02:30:10 +04:00
|
|
|
color = d3.scale.category20(),
|
|
|
|
arc = d3.svg.arc();
|
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);
|
|
|
|
|
2010-10-25 04:05:59 +04:00
|
|
|
vis.selectAll("g.arc")
|
2010-09-28 22:34:52 +04:00
|
|
|
.data(data)
|
Simplify data join. Add insert & empty.
The data join is now specified as a single function of data, as with all other
properties. This allows the key to be computed on the previously-bound data,
rather than requiring the key to be serialized into the DOM (say, as an
attribute). In the case that there is no previously-bound data, it is still
possible to access the associated node as the `this` context.
The `enter` operator no longer performs an append. For symmetry with the `exit`
operator, you must call `append` after obtaining the entering selection. This
requires a tiny bit more code, but should make the code more clear. Also, it
provides an opportunity to use a different instantiation operator, such as the
new `insert` operator. This takes a second argument, which is a selector for the
insert-before reference element. For example, the selector ":first-child" will
prepend nodes.
The `empty` operator allows you to query whether a selection is empty (i.e.,
contains zero matching nodes).
2011-01-31 22:00:35 +03:00
|
|
|
.enter().append("svg:g")
|
2010-09-28 22:34:52 +04:00
|
|
|
.attr("class", "arc")
|
2010-10-25 04:05:59 +04:00
|
|
|
.attr("transform", "translate(" + r1 + "," + r1 + ")")
|
|
|
|
.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,
|
2010-10-25 04:05:59 +04:00
|
|
|
next = data = arcs(d3.range(n).map(Math.random)),
|
2010-10-24 21:39:34 +04:00
|
|
|
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-25 04:05:59 +04:00
|
|
|
innerRadius: i & 1 ? r0 : (r0 + r1) / 2,
|
|
|
|
outerRadius: i & 1 ? (r0 + r1) / 2 : r1
|
2010-10-24 21:39:34 +04:00
|
|
|
}))
|
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
|
|
|
}
|
|
|
|
|
2010-10-25 04:05:59 +04:00
|
|
|
function arcs(values) {
|
|
|
|
var k = (2 * Math.PI) / values.reduce(function(p, d) { return p + d; }, 0),
|
2010-09-28 22:34:52 +04:00
|
|
|
a = 0;
|
2010-10-25 04:05:59 +04:00
|
|
|
return values.map(function(d, i) {
|
2010-09-28 22:34:52 +04:00
|
|
|
return {
|
|
|
|
startAngle: a,
|
2010-10-25 04:05:59 +04:00
|
|
|
endAngle: a += d * k,
|
|
|
|
innerRadius: r0,
|
|
|
|
outerRadius: r1
|
2010-09-28 22:34:52 +04:00
|
|
|
};
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
</script>
|
|
|
|
</body>
|
|
|
|
</html>
|