简体   繁体   English

使用d3,js在甜甜圈图中进行arctween和数据集更改

[英]arctween and dataset change in donut chart with d3,js

With the click of a button, I want to add a new dataset to my doughnut chart and have it transition the new dataset. 单击一个按钮,我想向我的甜甜圈图添加一个新的数据集,并让它转换新的数据集。 The code I've written sort of does that but it runs into an issue when the number of individual data within the dataset is different from the previous ie going from [1,2] to [1,2,3,4]. 我编写的代码可以做到这一点,但是当数据集中的单个数据数量与之前的不同(即从[1,2]变为[1,2,3,4])时,就会遇到问题。

I think the issue is that I need to create a new path whenever there the new dataset has more data, and remove paths whenever it has less. 我认为问题在于,只要新数据集具有更多数据,就需要创建一个新路径,而当数据集具有较少数据时,就需要删除路径。 However, when I try to append data in my click function, it will append it without removing the old paths and will overlap on the chart. 但是,当我尝试在click函数中附加数据时,它将在不删除旧路径的情况下附加数据,并将在图表上重叠。

Here is a version without appending, where the arctween will work but there will be empty pie arcs because I don't append path (arctween works half the time): http://jsfiddle.net/njrPF/1/ 这是一个没有附加的版本,其中arctween可以使用,但是会有空的圆弧,因为我不附加路径(arcween可以使用一半的时间): http : //jsfiddle.net/njrPF/1/

var pieW = 500;
var pieH = 500;
var innerRadius = 100;
var outerRadius = 200;

var results_pie = d3.layout.pie()
    .sort(null);
var pie_arc = d3.svg.arc()
    .innerRadius(innerRadius)
    .outerRadius(outerRadius);

var svg_pie = d3.select("#pieTotal")
    .attr("width", pieW)
    .attr("height", pieH)
    .append("g")
    .attr("transform", "translate(" + pieW / 2 + "," + pieH / 2 + ")")
    .attr("class", "piechart");

var pie_path = svg_pie.selectAll("path").data(results_pie([1, 2]))
    .enter().append("path")
    .attr("d", pie_arc)
    .each(function (d) {
    this._current = d;
}) // store the initial values
.attr("class", "vote_arc")
    .attr("value", function (d, i) {
    return (i - 1);
});


var pie_votes = [1, 2];
var pie_colors = ["#0f0", "#f00"];
$(svg_pie).bind("monitor", worker);
$(svg_pie).trigger("monitor");

function worker(event) {
    pie_path = pie_path.data(results_pie(pie_votes))
        .attr("fill", function (d, i) {
        return pie_colors[i];
    });

    pie_path.transition().duration(500).attrTween("d", arcTween).each('end', function (d) {
        if (d.value <= 0) {
            this.remove();
        }
    });
    setTimeout(function () {
        $(svg_pie).trigger("monitor");
    }, 500);
}

function arcTween(a) {
    var i = d3.interpolate(this._current, a);
    this._current = i(0);
    return function (t) {
        return pie_arc(i(t));
    };
}

$('button').click(function () {
    pie_votes = [];
    pie_colors = [];
    for (var i = 0; i < Math.floor(Math.random() * 6); i++) {
        //sets new values on pie arcs
        pie_votes.push(Math.floor(Math.random() * 10));
        pie_colors.push("#" + (Math.floor(Math.random() * 16777215)).toString(16));
    }
    pie_path = pie_path.data(results_pie(pie_votes))
        .attr("fill", function (d, i) {
        return pie_colors[i]
    });

    pie_path.transition().duration(500).attrTween("d", arcTween).each('end', function (d) {
        if (d.value <= 0) {
            this.remove();
        }
    });
});

Here is a version where I try to append new paths but they overlap: http://jsfiddle.net/njrPF/3/ 这是我尝试附加新路径但它们重叠的版本: http : //jsfiddle.net/njrPF/3/

var pieW = 500;
var pieH = 500;
var innerRadius = 100;
var outerRadius = 200;

var results_pie = d3.layout.pie()
    .sort(null);
var pie_arc = d3.svg.arc()
    .innerRadius(innerRadius)
    .outerRadius(outerRadius);

var svg_pie = d3.select("#pieTotal")
    .attr("width", pieW)
    .attr("height", pieH)
    .append("g")
    .attr("transform", "translate(" + pieW / 2 + "," + pieH / 2 + ")")
    .attr("class", "piechart");

var pie_path = svg_pie.selectAll("path").data(results_pie([1, 2]))
    .enter().append("path")
    .attr("d", pie_arc)
    .each(function (d) {
    this._current = d;
}) // store the initial values
.attr("class", "vote_arc")
    .attr("value", function (d, i) {
    return (i - 1);
});

function arcTween(a) {
    var i = d3.interpolate(this._current, a);
    this._current = i(0);
    return function (t) {
        return pie_arc(i(t));
    };
}

$('button').click(function () {
    pie_votes = [];
    pie_colors = [];
    for (var i = 0; i < Math.floor(Math.random() * 10); i++) {
        //sets new values on pie arcs
        pie_votes.push(Math.floor(Math.random() * 10));
        pie_colors.push("#" + (Math.floor(Math.random() * 16777215)).toString(16));
    }
    pie_path = pie_path.data(results_pie(pie_votes))
        .enter().append("path")
        .attr("d", pie_arc)
        .each(function (d) {
        this._current = d; }) // store the initial values
    .attr("class", "vote_arc")
        .attr("value", function (d, i) {
        return (i - 1);
    });
    pie_path.attr("fill", function (d, i) {
        return pie_colors[i]
    });

    pie_path.transition().duration(500).attrTween("d", arcTween).each('end', function (d) {
        if (d.value <= 0) {
            this.remove();
        }
    });
});

Thanks in advance. 提前致谢。

You need to handle the enter and exit selections as well as the update selection. 您需要处理输入和退出选择以及更新选择。 See for example this tutorial . 例如,参见本教程 The relevant code in your case would be 您情况下的相关代码为

pie_path = pie_path.data(results_pie(pie_votes));

pie_path.enter().append("path")
    .attr("d", pie_arc)
    .each(function (d) {
        this._current = d;
    }) // store the initial values
    .attr("class", "vote_arc")
        .attr("value", function (d, i) {
        return (i - 1);
    });

pie_path.exit().remove();

Complete example here . 这里完整的例子。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM