D3.js donut chart
smoothly animated labels, gradient fills, updatable
HTML
<div id="chart"></div>
JavaScript
function chart() {
"use strict";
var width = 500,
height = 400,
value = function (d) { return d[1]; },
label = function (d) { return d[0]; },
color = d3.scale.ordinal().range(['#d7191c', '#fdae61', '#ffffbf', '#a6d96a', '#1a9641']),
margins = [180, 30],
sort = null;
function my(selection) {
selection.each(function (data) {
// Fix the values and labels into greedily evaluated arrays
// This allows precomputation of sizes and values
data = data.map(function (d, i) {
return [Math.abs(value.call(data, d, i)), label.call(data, d, i)];
});
// Construct the pie and arc settings
var pie = d3.layout.pie().sort(sort).value(function (d) { return d[0]; }),
radius = Math.min(width - margins[0], height - margins[1]) / 2,
arc = d3.svg.arc()
.innerRadius(radius - 90) // TODO: configurable
.outerRadius(radius - 20),
rotation = function (d) {
return "rotate(" + (d.startAngle + d.endAngle) / 2 * (180 / Math.PI) + ")";
},
translation = function (d) {
return "translate(" +
Math.cos((d.startAngle + d.endAngle - Math.PI) / 2) * (radius - 7) + "," +
Math.sin((d.startAngle + d.endAngle - Math.PI) / 2) * (radius - 7) + ")";
},
textX = function (d) {
var mid = (d.startAngle + d.endAngle) / 2,
xsize = this.getBBox().width,
dist = Math.min(1, Math.abs(((mid + Math.PI / 2) % Math.PI) - Math.PI / 2) / (Math.PI / 12)),
dx = (mid > Math.PI) ? dist * -xsize / 2 + -xsize / 2 : (1 - dist) * -xsize / 2;
return dx + "px";
},
textY = function (d) {
...