实时更新折线图 - 不会顺利滚动屏幕(摆动)

时间:2016-09-14 13:04:47

标签: d3.js

我有一个用于显示实时数据的折线图。我已经阅读了https://bost.ocks.org/mike/path/,我可以顺利进入屏幕,但是对于我的生活,当我从屏幕移除数据点和相应的线段时,我不能让它“摆动” 。

以下是我正在更新线和x轴的代码部分。

lineselection.datum(data)
    .transition()
    .duration(1000)
    .ease(d3.easeLinear)
    .attr('d', line)
    .attr('transform', 'translate(' + (xScale.range()[0]/data.length) + ',0)');

xScale = d3.scaleTime()
    .domain([time, start_time])
    .range([width - (margin * 2), 0])
    .clamp(true);

g.selectAll('.x.axis')
    .transition()
    .duration(1000)
    ease(d3.easeLinear)
    .call(xAxis);

这会产生一个漂亮的平滑折线图,其中新的线条部分被绘制在剪辑路径之外,然后向左平移到视图中。 x轴与它完美地滚动。

在我的数据更新方法中,我检查是否在我的数据视图窗口中(即,我们只想查看最后一个,比如说60秒的数据)。如果一个点落在时间范围之外,我们将其删除,并更新start_time以反映。

if ((time_frame + start_time) < time){
    for (d = 0; d < data.length; d++){
        if ((data[d].x + time_frame) < time){
            data.shift();
        }
        else{
            start_time = data[d].x;
            break;
        }
    }
}

我对JS和D3都比较新,所以请保持温和。任何帮助,将不胜感激。我错过了一些明显的东西吗?

这是一个jsfiddle。 https://jsfiddle.net/3kn56mb7/2/

编辑。添加了一个jsfiddle。

2 个答案:

答案 0 :(得分:2)

这是更新的jsfiddle。 https://jsfiddle.net/3kn56mb7/12/

感谢elias帮助我解决这个问题!

这是我的绘图功能。我使用selection.interrupt()来克服抖动。

function draw(){
var line = d3.line()
    .x(function(d) { return xScale(d.x); })
    .y(function(d) { return yScale(d.y); });

var lineselection = svg.selectAll('.line_')
    .select('path');


lineselection.interrupt()
        .transition()
    .duration(duration)
    .ease(d3.easeLinear)
    .attr('transform', 'translate(' + -(xScale.range()[0]/((duration / 100)-2)) + ',' + margin + ')');


if (data[0].x < time - time_frame - duration ){
        console.log('shift');
            data.shift();
}

lineselection.attr('d',line)
    .attr('transform', 'translate(0,' + margin + ')');



start_time = time - (duration * 2) - time_frame;

xScale.domain([time, time + (duration * 2) - time_frame])
    .range([width - (margin *2),0]);

d3.select('body')
    .select('svg')
    .select('g')
    .selectAll('.x.axis')
    .transition()
    .duration(duration)
    .ease(d3.easeLinear)
    .call(xAxis);

}

编辑:我更新了代码以反映selection.interrupt()更改以及包含整个绘图功能。我还更新了jsfiddle链接。

编辑2 :修正了保证金错误并更新了jsfiddle链接。

编辑3 :我回来使用它作为参考。一年后我正在看这段代码,并且无法弄清楚为什么我做了一些奇怪的数学运算。我一定是在呼吸柴油烟雾。在任何情况下,我重新计算数学,以便它有意义(为什么我将持续时间除以100并减去2)?

更改了此内容:https://jsfiddle.net/3kn56mb7/11/

.attr('transform', 'translate(' + -(xScale.range()[0]/((duration / 100)-2)) + ',' + margin + ')');

对此:https://jsfiddle.net/3kn56mb7/12/

.attr('transform', 'translate(' + -(xScale(data[data.length-1].x) -xScale.range()[0]) + ',' + margin + ')');

我现在在每个绘制周期中获取最后一个数据点,并获取其时间(x值)并将其转换为该范围内的位置。然后我减去最大范围(宽度 - 边距* 2)。使差异为负值,使其向左移动。

答案 1 :(得分:1)

基本问题是您的数据元素的索引正在通过删除过时的元素而发生变化。我在我的一个项目中遇到了同样的问题,并通过以下方式解决了这个问题:

我建议您在两个单独的步骤中完成转换中的操作:

  • 删除元素时,使用新索引绘制一个新路径 - 立即执行此操作,不进行转换,因此不会出现摆动
  • 完成此操作后,可能会发生转换,这只是转换,在此期间不会删除任何元素