转换

时间:2015-10-26 17:56:14

标签: javascript d3.js svg

简单SVG,x轴上的时间刻度为最后5秒,每隔一秒我添加一个圆圈,每隔100ms从右向左移动所有现有圆圈。

var data = [];

setInterval(function() {

    var now = new Date();
    var fiveSecAgo = new Date(now.getTime() - 5000);
    x.domain([fiveSecAgo, now]);

    svg.selectAll("circle")
        .transition()
        .ease("linear")
        .duration(100)
        .attr("cx", function(d) {
            return x(d.date);
        });

}, 100);

// add circle every second
setInterval(function() {
    data.push({
        date: new Date()
    });

    svg.selectAll("circle")
        .data(data).enter()
        .append("svg:circle")
        .attr("r", 4)
        .attr("cx", function(d) {
            return x(d.date);
        })
        .attr("cy", height / 2);

}, 1000);

Working fiddle

现在这一切都很好,但是在前5秒之后,将会有负x值(超过5秒)的元素,所以我想删除它们,保持最后5个内现有元素的平滑过渡秒。

所以我的方法是让我的数据数据只包含最后5秒:

for (var i = 0; i < data.length; i++) {
    if (data[i].date < fiveSecAgo) {
        data.shift();
    } else {
        break;
    }
}

在转换现有的圈子然后执行.exit()。remove()之前。虽然旧元素将被删除,但转换不再平稳。

1 个答案:

答案 0 :(得分:2)

问题是默认情况下,D3是按索引匹配数据。也就是说,您修改的数据与错误的DOM元素匹配,因此您会看到它们以奇怪的方式移动。通过向.data()提供关键功能可以很容易地解决这个问题,告诉D3如何进行匹配:

.data(data, function(d) { return d.date; })

此外,修改迭代的数组是不安全的,所以不要在循环内部.shift()。在你的情况下,它足以做到

if(data[0].date < fiveSecAgo) data.shift();

完整演示here。我也清理了其他一些东西。