我正在根据时间序列数据制作d3图表。我想根据用户实时指定的时间窗口绘制移动平均值。 所有行将共享相同的数据集。 我正在实现常规更新模式(我相信),但是,当我更改数据集时,除非显式调用更新函数,否则不会发生更新。但是,这可以为数组中的每个元素创建一个节点(在旧元素之上创建一个新的DOM元素),而不是仅添加更新的元素。我觉得我对D3或javascript本身有一些根本性的误解。这是我的代码的最小工作示例:
简而言之,我的图表具有setInterval方法,该方法可添加到数据集中并更新图表上的所有折线。每行共享图表数据,但是将以不同的方式转换数据。
window.onload = function() {
let mychart = chart( '#chart' );
let props1 = {
'className': 'line-1',
'Color': 'red',
'y': function( d ) { return d + 25; }
}
let line1 = line( mychart, props1 );
mychart.addPlot( line1 );
mychart.stream();
}
//need to find best way to share data across all indicators
var chart = function(svg_id) {
let data = [ 0, 1, 2, 3, 4, 5];
let plots = [];
let svg = ( function( ) {
return d3.select( svg_id + '-container' ).append( 'svg' )
.attr( 'height', 500 )
.attr( 'width', 1000 )
.attr( 'id', svg_id.replace('#', '' ))
})();
let xscale = d3.scaleLinear()
.domain( [0, 100] )
.range( [10, 990] )
let addPlot = function( plot ) {
plots.push( plot );
}
let stream = function() {
setInterval( function() {
data.push( Math.random(0, 1) * 100);
for( var i = 0; i < plots.length; i++ ) {
plots[i].update();
}
}, 1000);
}
return {
'svg': svg,
'xscale': xscale,
'data': data,
'addPlot': addPlot,
'stream': stream,
}
}
var line = function( chart, props ) {
let data = chart.data;
let xscale = chart.xscale;
let svg = chart.svg;
let buildLine = d3.line()
.x( function(d, i ) { return xscale( i ) + i*1; })
.y( function(d) { return props.y( d ); })
let update = function() {
let line = svg.selectAll( props.className ).data( data );
line.enter()
.append( 'path' )
.attr( 'stroke', props.Color )
.attr( 'stroke-width', 2 )
.attr( 'class', props.className )
.attr( 'fill', 'none' )
.merge( line )
.attr( 'd', buildLine( data ))
line.exit().remove();
}
return {
'update': update,
}
}
我在网上发现了很多关于没有添加节点的信息,但是关于每次迭代都重新绘制d3以及每次迭代都添加节点的事情却一无所获。谢谢。
答案 0 :(得分:0)
我不确定,但是也许您可以看一下:Key functions
作为.data( data )
的第二个参数,您可以提供一个唯一标识数据点的函数。像.data( data, function(d) { return d.someUniqueId; })
D3可以使用此密钥来更新DOM元素,而不必重新生成它们,据我所知from Mike Bostock's post。
答案 1 :(得分:0)
我在d3路径https://www.dashingd3js.com/svg-paths-and-d3js上使用本教程解决了此问题。关键是selectAll不适用于路径,因为一行仅是一个“路径”元素,因此仅需添加。我正在使用jquery删除该行,因此仍然有点hacky,因为我确定D3可以做到这一点。但是这里有一个更新的初始化和更新功能。
let init = function() {
svg.append( 'path' )
.attr( 'd', buildLine( data ))
.attr( 'stroke', props.Color )
.attr( 'stroke-width', 2 )
.attr( 'class', props.className )
.attr( 'fill', 'none' )
}
let update = function( newdata ) {
data.push( newdata );
$( '.' + props.className ).remove();
init();