Javascript D3过渡线发生两次
我对D3非常陌生,我正试图根据这里的一个片段粗略地制作一个简单的实时图表: 我希望能够在移动的实时图表中添加许多行,并从web套接字更新这些行(我知道怎么做!!) 当我尝试添加第二行时,图表不会顺利更新,我认为转换被调用了两次。感谢您的帮助 代码如下,但这里有一把小提琴Javascript D3过渡线发生两次,javascript,d3.js,Javascript,D3.js,我对D3非常陌生,我正试图根据这里的一个片段粗略地制作一个简单的实时图表: 我希望能够在移动的实时图表中添加许多行,并从web套接字更新这些行(我知道怎么做!!) 当我尝试添加第二行时,图表不会顺利更新,我认为转换被调用了两次。感谢您的帮助 代码如下,但这里有一把小提琴 var n=243; var random=d3.randomNormal(0.2); var持续时间=500; var now=新日期(Date.now()-持续时间); var svg=d3。选择(“svg”), 边距={顶
var n=243;
var random=d3.randomNormal(0.2);
var持续时间=500;
var now=新日期(Date.now()-持续时间);
var svg=d3。选择(“svg”),
边距={顶部:20,右侧:20,底部:20,左侧:40},
宽度=+svg.attr(“宽度”)-margin.left-margin.right,
高度=+svg.attr(“高度”)-margin.top-margin.bottom,
g=svg.append(“g”).attr(“transform”、“translate”(+margin.left+)、“+margin.top+”);
var x=d3.scaleTime()
.domain([现在-(n-2)*持续时间,现在-持续时间])
.范围([0,宽度]);
变量y=d3.scaleLinear()
.domain([-1,1])
.范围([高度,0]);
var lineNames=[];
变量行={};
变量数据={};
var line=d3.line()
.曲线(d3.曲线基)
.x(函数(d,i){返回x(现在-(n-1-i)*持续时间);})
.y(函数(d,i){返回y(d);});
g、 附加(“defs”)。附加(“clipPath”)
.attr(“id”、“剪辑”)
.append(“rect”)
.attr(“宽度”,宽度)
.attr(“高度”,高度);
var轴=g.append(“g”)
.attr(“类”、“轴--x”)
.attr(“变换”、“平移(0)、+y(0)+”)
.call(d3.axisBottom(x));
g、 附加(“g”)
.attr(“类”、“轴--y”)
.调用(d3.左(y));
创建线(“一”);
createLine(“两个”);
d3.选择全部(“.行”)
.transition()
.持续时间(持续时间)
.ease(d3.easeLinear)
。开启(“开始”,勾选);
函数createLine(名称){
lineNames.push(name);
数据[名称]=d3.range(n).map(随机);
行[名称]=d3.line()
.曲线(d3.曲线基)
.x(函数(d,i){返回x(现在-(n-1-i)*持续时间);})
.y(函数(d,i){返回y(d);});
g、 附加(“g”)
.attr(“剪辑路径”、“url(#剪辑)”)
.append(“路径”)
.数据(数据[名称])
.attr(“类”、“行”);
}
函数tick(){
var指数;
var i;
对于(i=0;i
问题似乎是当一行调用“tick”时更新所有行的数据。您会注意到,您的示例在1行中效果很好,而在3行中效果更差。这是因为函数tick中有for循环。D3中的数据绑定非常有用,但需要一些时间才能习惯使用我所做的两个主要代码更改是将line()设为变量,并从tick函数中删除for循环。更新的fiddle(我试图注释掉原始代码,这样您就可以很容易地看到差异):
清理小提琴:问题似乎是在一行调用“tick”时更新所有行的数据。您会注意到,您的示例在1行中效果很好,而在3行中效果更差。这是因为函数tick中有for循环。D3中的数据绑定非常有用,但需要一些时间才能习惯使用
我所做的两个主要代码更改是将line()设为变量,并从tick函数中删除for循环。更新的fiddle(我试图注释掉原始代码,这样您就可以很容易地看到差异):
清理小提琴:我最初的倾向是,tick函数被调用的频率是它应该调用的两倍。我可能是错的,但看起来函数每行调用一次,但每次调用都会影响两行。我本以为每一行都会打勾,只影响那一行。我已经添加了一个提琴来显示问题。我最初的倾向是,tick函数被调用的频率是它应该调用的两倍。我可能是错的,但看起来函数每行调用一次,但每次调用都会影响两行。我本以为每一行都会打勾,只影响那一行。或者勾选被调用一次并影响两行。我添加了一个小提琴来显示问题。好的,我想我有一点理解。我想我把“line”函数和屏幕上表示线条的路径搞混了。你的提琴有点让人困惑,但我还是想弄明白了。我在这里整理了一下:对不起,小提琴太乱了。我试图在给出答案和展示答案之间取得平衡。在开发工具的tick函数中设置一个断点非常有用,然后看看“this”包含什么。该框架将为您跟踪许多事情。我清理了小提琴,把它添加到原来的帖子里。好吧,我想我有点理解了。我想我把“line”函数和屏幕上表示线条的路径搞混了。你的提琴有点让人困惑,但我还是想弄明白了。我在这里整理了一下:对不起,小提琴太乱了。我试图在给出答案和展示答案之间取得平衡。在开发工具的tick函数中设置一个断点非常有用,然后看看“this”包含什么。该框架将为您跟踪许多事情。我清理了小提琴,把它添加到原来的帖子里。
var n = 243;
var random = d3.randomNormal(0, .2);
var duration = 500;
var now = new Date(Date.now() - duration);
var svg = d3.select("svg"),
margin = {top: 20, right: 20, bottom: 20, left: 40},
width = +svg.attr("width") - margin.left - margin.right,
height = +svg.attr("height") - margin.top - margin.bottom,
g = svg.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var x = d3.scaleTime()
.domain([now - (n - 2) * duration, now - duration])
.range([0, width]);
var y = d3.scaleLinear()
.domain([-1, 1])
.range([height, 0]);
var lineNames = [];
var lines = {};
var data = {};
var line = d3.line()
.curve(d3.curveBasis)
.x(function(d, i) { return x(now - (n - 1 - i) * duration); })
.y(function(d, i) { return y(d); });
g.append("defs").append("clipPath")
.attr("id", "clip")
.append("rect")
.attr("width", width)
.attr("height", height);
var axis = g.append("g")
.attr("class", "axis axis--x")
.attr("transform", "translate(0," + y(0) + ")")
.call(d3.axisBottom(x));
g.append("g")
.attr("class", "axis axis--y")
.call(d3.axisLeft(y));
createLine("one");
createLine("two");
d3.selectAll(".line")
.transition()
.duration(duration)
.ease(d3.easeLinear)
.on("start", tick);
function createLine(name) {
lineNames.push(name);
data[name] = d3.range(n).map(random);
lines[name] = d3.line()
.curve(d3.curveBasis)
.x(function(d, i) { return x(now - (n - 1 - i) * duration); })
.y(function(d, i) { return y(d); });
g.append("g")
.attr("clip-path", "url(#clip)")
.append("path")
.datum(data[name])
.attr("class", "line");
}
function tick() {
var index;
var i;
for (i = 0; i < lineNames.length; ++i) {
index = lineNames[i];
// Push a new data point onto the back.
data[index].push(random());
// Redraw the line.
d3.select(this)
.attr("d", lines[index])
.attr("transform", null);
// Pop the old data point off the front.
data[index].shift();
}
now = new Date();
x.domain([now - (n - 2) * duration, now - duration]);
axis.transition()
.duration(duration)
.ease(d3.easeLinear)
.call(d3.axisBottom(x));
// Slide it to the left.
d3.active(this)
.attr("transform", "translate(" + x(now - (n - 1) * duration) + ")")
.transition()
.on("start", tick);
}
var line = d3.line()
.curve(d3.curveBasis)
.x(function(d, i) { return x(now - (n - 1 - i) * duration); })
.y(function(d, i) { return y(d); });
function tick() {
var index;
var i;
// Push a new data point onto the back.
this.__data__.push(random());
// Redraw the line.
d3.select(this)
.attr("d", line)
.attr("transform", null);
// Pop the old data point off the front.
this.__data__.shift();
now = new Date();
x.domain([now - (n - 2) * duration, now - duration]);
axis.transition()
.duration(duration)
.ease(d3.easeLinear)
.call(d3.axisBottom(x));
// Slide it to the left.
d3.active(this)
.attr("transform", "translate(" + x(now - (n - 1) * duration) + ")")
.transition()
.on("start", tick);
}