散点图上的plot/add节点如何使用d3一一对应?
How to use d3 to plot/add node on scatter plot one by one?
我对 D3.js 和 Javascript 都很陌生。对不起,如果问一些愚蠢的事情。
我刚刚完成了 D3 的教程,现在可以绘制保存在我的 csv-file 中的所有数据。(通过 d3.csv
函数加载)
我很好奇是否可以一个一个地绘制点而不是一次绘制所有点?
var dataset;
d3.csv("testcase.csv", function(data) {
dataset = data;
var w = $(window).width();
var h = $(window).height();
var svg = d3.select("body")
.append("svg")
.attr({
width: w,
height: h,
});
function draw(data){
var circle = svg.selectAll("circle")
.data(data);
circle.enter().append("circle")
.attr({
"cx": data["x"],
"cy": data["y"],
"r": data["r"],
"fill": "rgb(0,0,0)",
});
}
draw(dataset[0]);
var index = 1;
setInterval(function() {
if(index<dataset.length){
draw(dataset[index]);
index++;
}
}, 1500);
这就是我此时绘制点的结果,在 csv 文件中它保存了点的坐标及其半径。例如:
x,y,r
100,100,50
200,100,30
400,300,20
500,400,50
470,800,40
400,600,40
我正在尝试使用 setInterval
函数让它一个一个地绘制点,但它没有绘制任何东西(包括应该由 draw(dataset[0])
触发的第一个)
并且在使用console.log
函数检查值是否正确时,似乎完全正常。
the output of console pad
怎么了?感谢您的帮助:/
所以,您遇到了一个相当常见的逻辑错误,它是 d3 的新手。每次调用绘图函数时,您还重新绑定了数据。但是,除了将新数据告知 d3 之外,这还会清除 d3 的旧数据内存。因此,您实际上是在告诉 d3:这个新数据是真实的,忘记我过去告诉过您的任何数据。
好吧,上面说的有点简单
d3 实际上并没有忘记您已经告诉它的内容。但是,它需要一种方法来了解什么是新的、什么已经存在以及什么是旧的。为此,.data
根据每个数据在数据数组中的索引为每个数据分配一个键。因为每次你只绑定一个元素,它总是得到一个 0 的键。因此,d3 永远不会认为你要求它绑定新的东西。
要解决这个问题,请将关键函数传递给 data
、as described in in the documentation。
您的代码应该类似于:
function draw(data, key){
var circle = svg.selectAll("circle")
.data(data, function(d){ return key; });
circle.enter().append("circle")
.attr({
"cx": data["x"],
"cy": data["y"],
"r": data["r"],
"fill": "rgb(0,0,0)",
});
}
draw(dataset[0], 0);
var index = 1;
setInterval(function() {
if(index<dataset.length){
draw(dataset[index], index);
index++;
}
}, 1500);
这有道理吗?我强烈建议您通读文档。这就是我学习的方式,随着文档的发展,它的布局非常好,易于理解,还有大量示例。
根据 Matthew 的回答,如果您使用 d3 转换而不是 setInterval,那么您不必构建循环来单独处理节点,也可以避免他描述的问题(至少在第一次通过时,添加更多稍后节点,您将再次需要数据密钥)
var data = "x,y,r\n"+
"100,100,50\n"+
"200,100,30\n"+
"400,300,20\n"+
"500,400,50\n"+
"470,800,40\n"+
"400,600,40\n"
;
var dataset = d3.csv.parse (data);
var svg = d3.select("body")
.append("svg")
.attr({
width: 600,
height: 400,
});
var circle = svg.selectAll("circle")
.data(dataset);
circle.enter().append("circle")
.each (function (d,i) {
d3.select(this).transition()
.delay(i * 1200) // <- this does what you intended setinterval to do
.attr({
"cx": d.x,
"cy": d.y,
"r": d.r,
"fill": "rgb(0,0,0)",
});
});
;
我对 D3.js 和 Javascript 都很陌生。对不起,如果问一些愚蠢的事情。
我刚刚完成了 D3 的教程,现在可以绘制保存在我的 csv-file 中的所有数据。(通过 d3.csv
函数加载)
我很好奇是否可以一个一个地绘制点而不是一次绘制所有点?
var dataset;
d3.csv("testcase.csv", function(data) {
dataset = data;
var w = $(window).width();
var h = $(window).height();
var svg = d3.select("body")
.append("svg")
.attr({
width: w,
height: h,
});
function draw(data){
var circle = svg.selectAll("circle")
.data(data);
circle.enter().append("circle")
.attr({
"cx": data["x"],
"cy": data["y"],
"r": data["r"],
"fill": "rgb(0,0,0)",
});
}
draw(dataset[0]);
var index = 1;
setInterval(function() {
if(index<dataset.length){
draw(dataset[index]);
index++;
}
}, 1500);
这就是我此时绘制点的结果,在 csv 文件中它保存了点的坐标及其半径。例如:
x,y,r
100,100,50
200,100,30
400,300,20
500,400,50
470,800,40
400,600,40
我正在尝试使用 setInterval
函数让它一个一个地绘制点,但它没有绘制任何东西(包括应该由 draw(dataset[0])
触发的第一个)
并且在使用console.log
函数检查值是否正确时,似乎完全正常。
the output of console pad
怎么了?感谢您的帮助:/
所以,您遇到了一个相当常见的逻辑错误,它是 d3 的新手。每次调用绘图函数时,您还重新绑定了数据。但是,除了将新数据告知 d3 之外,这还会清除 d3 的旧数据内存。因此,您实际上是在告诉 d3:这个新数据是真实的,忘记我过去告诉过您的任何数据。
好吧,上面说的有点简单
d3 实际上并没有忘记您已经告诉它的内容。但是,它需要一种方法来了解什么是新的、什么已经存在以及什么是旧的。为此,.data
根据每个数据在数据数组中的索引为每个数据分配一个键。因为每次你只绑定一个元素,它总是得到一个 0 的键。因此,d3 永远不会认为你要求它绑定新的东西。
要解决这个问题,请将关键函数传递给 data
、as described in in the documentation。
您的代码应该类似于:
function draw(data, key){
var circle = svg.selectAll("circle")
.data(data, function(d){ return key; });
circle.enter().append("circle")
.attr({
"cx": data["x"],
"cy": data["y"],
"r": data["r"],
"fill": "rgb(0,0,0)",
});
}
draw(dataset[0], 0);
var index = 1;
setInterval(function() {
if(index<dataset.length){
draw(dataset[index], index);
index++;
}
}, 1500);
这有道理吗?我强烈建议您通读文档。这就是我学习的方式,随着文档的发展,它的布局非常好,易于理解,还有大量示例。
根据 Matthew 的回答,如果您使用 d3 转换而不是 setInterval,那么您不必构建循环来单独处理节点,也可以避免他描述的问题(至少在第一次通过时,添加更多稍后节点,您将再次需要数据密钥)
var data = "x,y,r\n"+
"100,100,50\n"+
"200,100,30\n"+
"400,300,20\n"+
"500,400,50\n"+
"470,800,40\n"+
"400,600,40\n"
;
var dataset = d3.csv.parse (data);
var svg = d3.select("body")
.append("svg")
.attr({
width: 600,
height: 400,
});
var circle = svg.selectAll("circle")
.data(dataset);
circle.enter().append("circle")
.each (function (d,i) {
d3.select(this).transition()
.delay(i * 1200) // <- this does what you intended setinterval to do
.attr({
"cx": d.x,
"cy": d.y,
"r": d.r,
"fill": "rgb(0,0,0)",
});
});
;