block by pjsier 41f5e06b46e4ed69fd1c27d5ee9cce94

Donut Chart, Text Transition

Full Screen

script.js

function donutChart() {
    var margin = { top: 10, right: 10, bottom: 40, left: 10 },
        width = 400,
        height = 400,
        donutWidth = 60,
        format = d3.format(",d"),
        dataValue = function (d) { return +d.data; },
        fillValue = function(d) { return d.fill; },
        color = "steelblue";

    function chart(selection) {
        selection.each(function (data) {
            data = data.map(function (d, i) {
                return { data: dataValue(d), fill: fillValue(d) };
            });
            var pie = d3.pie()
                .value(dataValue)
                .sort(null);

            var radius = Math.min(width - margin.left - margin.right, height - margin.top - margin.bottom) / 2;
            var arc = d3.arc()
                .innerRadius(radius - donutWidth)
                .outerRadius(radius);

            // https://bl.ocks.org/mbostock/1346410
            function arcTween(a) {
                var i = d3.interpolate(this._current, a);
                this._current = i(0);
                return function (t) {
                    return arc(i(t));
                };
            }

            var svg = d3.select(this).selectAll("svg").data([data]);
            var gEnter = svg.enter().append("svg").append("g");
            gEnter.selectAll().data(pie).enter().append("path")
                .attr("d", arc)
                .each(function (d) { this._current = d; });

            var fillData = data.filter(function(d) { return d.fill; });
            gEnter.selectAll().data(fillData)
                .enter().append("text")
                    .attr("id", "text-val")
                    .attr("text-anchor", "middle")
                    .attr("font-size", "24px")
                    .attr("x", 0)
                    .attr("y", 0)
                    .text(function(d) { return format(d.data); });

            var svg = selection.select("svg");
            svg.attr('width', width).attr('height', height)
            var g = svg.select("g")
                .attr("transform", "translate(" +
                ((width - margin.left - margin.right) / 2) + "," +
                ((height - margin.top - margin.bottom) / 2) + ")");

            var donutPath = g.selectAll("path")
                .data(pie)
                .attr("fill", function (d) { return d.data.fill ? color : "transparent"; })
                .transition()
                    .duration(1000)
                    .attrTween("d", arcTween);

            d3.select("#text-val")
                .transition()
                    .duration(1000)
                    .tween("text", function () {
                        var that = d3.select(this),
                            i = d3.interpolateNumber(that.text().replace(/,/g, ""), fillData[0].data);
                        return function (t) { that.text(format(i(t))); };
                    });

        });
    }

    chart.margin = function (_) {
        if (!arguments.length) return margin;
        margin = _;
        return chart;
    };

    chart.width = function (_) {
        if (!arguments.length) return width;
        width = _;
        return chart;
    };

    chart.height = function (_) {
        if (!arguments.length) return height;
        height = _;
        return chart;
    };

    chart.donutWidth = function (_) {
        if (!arguments.length) return donutWidth;
        donutWidth = _;
        return chart;
    };

    chart.dataValue = function (_) {
        if (!arguments.length) return dataValue;
        dataValue = _;
        return chart;
    };

    return chart;
}

index.html

<!DOCTYPE html>
<html>

<head>
    <title>Donut Chart, Text Transition</title>
    <meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
    <meta charset='utf-8' />
    <script src="https://d3js.org/d3.v4.min.js"></script>
    <style>
        body {
            font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
        }

        #chart {
            max-width: 600px;
            max-height: 400px;
        }
    </style>
</head>

<body>
    <div id="chart"></div>
    <script src="script.js"></script>
    <script>
        function randNumberBounds(min, max) {
            min = Math.ceil(min);
            max = Math.floor(max);
            return Math.floor(Math.random() * (max - min)) + min;
        }

        var donut = donutChart();
        var data = [
            { data: 5000, fill: true },
            { data: 5000, fill: false }
        ];

        function resize() {
            if (d3.select("#chart svg").empty()) {
                return;
            }
            donut.width(+d3.select("#chart").style("width").replace(/(px)/g, ""))
                .height(+d3.select("#chart").style("height").replace(/(px)/g, ""));
            d3.select("#chart").call(donut);
        }

        document.addEventListener("DOMContentLoaded", function () {
            d3.select("#chart").datum(data).call(donut);
            d3.select(window).on('resize', resize);
            resize();
        });

        window.setInterval(function() {
            var randNum = randNumberBounds(0, 10000);
            var emptyNum = 10000 - randNum;
            var data = [
                { data: randNum, fill: true},
                { data: emptyNum, fill: false }
            ];
            d3.select("#chart").datum(data).call(donut);
        }, 2000);
    </script>
</body>

</html>