【问题标题】:arctween and dataset change in donut chart with d3,js圆环图中的 arctween 和数据集更改与 d3,js
【发布时间】:2014-01-13 17:39:03
【问题描述】:

单击一个按钮,我想将一个新数据集添加到我的圆环图并让它转换新数据集。我编写的代码可以做到这一点,但是当数据集中的单个数据数量与以前不同时,即从 [1,2] 到 [1,2,3,4],它会遇到问题。

我认为问题在于,只要新数据集有更多数据,我就需要创建一个新路径,并在它有更少数据时删除路径。但是,当我尝试在 click 函数中附加数据时,它会在不删除旧路径的情况下附加数据,并且会在图表上重叠。

这是一个没有附加的版本,arctween 可以工作,但会有空的圆弧,因为我不附加路径(arctween 有一半的时间工作): 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();
        }
    });
});

这是我尝试附加新路径但它们重叠的版本: 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();
        }
    });
});

提前致谢。

【问题讨论】:

    标签: javascript jquery d3.js


    【解决方案1】:

    您需要处理进入和退出选择以及更新选择。参见例如this tutorial。您的案例中的相关代码是

    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();
    

    完整示例here

    【讨论】:

    • 谢谢。有没有办法在 remove() 之后进行回调?会是像 remove(callback) 这样的东西吗?
    • 你想在回调中做什么? .remove() 应该是最后一件事。
    • 基本上我将饼图数据更改放入一个函数中,然后传入数据和颜色。我希望它以某种方式进行动画处理,如果您要推入一组全新的数据(数据数组中的长度不同),它将通过首先将所有内容设置为 0 来处理它(所以它就像 arctween 是'emptying'),删除数据,初始化新数据集,然后为新数据设置动画。所以这基本上需要 4 次调用上述代码的更改版本来操纵饼图的移动。
    • 您可以为每个过渡设置一个.delay(),这应该可以让您做您想做的事。您可以简单地延迟进入转换的开始,直到退出转换完成。
    • .delay() 是否相对于帧率发生?似乎只是在特定时间之后,所以较慢的系统可能会表现得很奇怪?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-04
    相关资源
    最近更新 更多