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) {
                  ...