如何在d3.js中创建甜甜圈图?

时间:2020-07-16 08:16:15

标签: javascript html d3.js responsive donut-chart

我正在尝试在d3.js中创建响应式甜甜圈图。

我在d3.js中编写了图表代码,但是我无法根据预期的图表进行创建。

这里是actual chart,而我正在尝试实现的是这个one

下面的我的d3.js脚本:

document.addEventListener('DOMContentLoaded', function(e) {

    var dataset = {
        
        oranges: [200, 200, 200, 200]
    };

    var width = 960,
      height = 500,
      radius = Math.min(width, height) / 2;

    var enterClockwise = {
        startAngle: 0,
        endAngle: 0
    };

    var enterAntiClockwise = {
        startAngle: Math.PI * 2,
        endAngle: Math.PI * 2
    };

    var color = d3.scale.category20();

    var pie = d3.layout.pie()
      .sort(null);

    var arc = d3.svg.arc()
      .innerRadius(radius - 100)
      .outerRadius(radius - 20);

    var svg = d3.select('#Donut-chart').append('svg')
         .attr('id', 'Donut-chart-render')
         .attr("width", '100%')
         .attr("height", '100%')
         .attr('viewBox', (-width / 2) + ' ' + (-height / 2) + ' ' + width + ' ' + height)
         .attr('preserveAspectRatio', 'xMinYMin')

    var path = svg.selectAll("path")
      .data(pie(dataset.apples))
      .enter().append("path")
        .attr("fill", function (d, i) { return color(i); })
        .attr("d", arc(enterClockwise))
        .each(function (d) {
            this._current = {
                data: d.data,
                value: d.value,
                startAngle: enterClockwise.startAngle,
                endAngle: enterClockwise.endAngle
            }
        });

    path.transition()
        .duration(750)
        .attrTween("d", arcTween);

    d3.selectAll("input").on("change", change);

    var timeout = setTimeout(function () {
        d3.select("input[value=\"oranges\"]").property("checked", true).each(change);
    }, 2000);

    function change() {
        clearTimeout(timeout);
        path = path.data(pie(dataset[this.value]));
        path.enter().append("path")
            .attr("fill", function (d, i) {
                return color(i);
            })
            .attr("d", arc(enterAntiClockwise))
            .each(function (d) {
                this._current = {
                    data: d.data,
                    value: d.value,
                    startAngle: enterAntiClockwise.startAngle,
                    endAngle: enterAntiClockwise.endAngle
                };
            }); // store the initial values

        path.exit()
            .transition()
            .duration(750)
            .attrTween('d', arcTweenOut)
            .remove() // now remove the exiting arcs

        path.transition().duration(750).attrTween("d", arcTween); // redraw the arcs
    }

    function arcTween(a) {
        var i = d3.interpolate(this._current, a);
        this._current = i(0);
        return function (t) {
            return arc(i(t));
        };
    }
    function arcTweenOut(a) {
        var i = d3.interpolate(this._current, { startAngle: Math.PI * 2, endAngle: Math.PI * 2, value: 0 });
        this._current = i(0);
        return function (t) {
            return arc(i(t));
        };
    }


    function type(d) {
        d.value = +d.value;
        return d;
    }

});

我一直在解决这个问题,所以将为您提供有益的解答。

谢谢!

1 个答案:

答案 0 :(得分:0)

要将标签添加到饼图中,请使用arc.centroid()。您首先需要一个arc generator。请参阅this example以供参考。

  svg.append("g")
      .attr("font-family", "sans-serif")
      .attr("font-size", 12)
      .attr("text-anchor", "middle")
    .selectAll("text")
    .data(arcs)
    .join("text")
      .attr("transform", d => `translate(${arc.centroid(d)})`)
      .call(text => text.append("tspan")
          .attr("y", "-0.4em")
          .attr("font-weight", "bold")
          .text(d => d.data.name))
      .call(text => text.filter(d => (d.endAngle - d.startAngle) > 0.25).append("tspan")
          .attr("x", 0)
          .attr("y", "0.7em")
          .attr("fill-opacity", 0.7)
          .text(d => d.data.value.toLocaleString()));