在d3中的for循环中绘制多行 [英] Plot multiple lines in a for loop in d3
问题描述
在线上有很多情况,如果仅添加svg对象一次,如何在d3中绘制几条线,例如
There are many cases online how to plot couple of lines in d3 if you add svg object only once, such as
svg.selectAll("line")
.data(dataset)
.enter().append("line")
.style("stroke", "black") // colour the line
.attr("x1", function(d) { console.log(d); return xScale(d.x1); })
.attr("y1", function(d) { return yScale(d.y1); })
.attr("x2", function(d) { return xScale(d.x2); })
.attr("y2", function(d) { return yScale(d.y2); });
此图创建一行.我想在像
This plot create one line. I want to create many different lines in an array smth like
var svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
for (a_ind=1; a_ind<3; a_ind++){
dataset_a=dataset.filter(function(d) { return (d.a==a_ind)})
svg.selectAll("line")
.data(dataset_a) - //!!! using new dataset in each cycle
.enter().append("line")
.style("stroke", "black") // colour the line
.attr("x1", function(d) { console.log(d); return xScale(d.x1); })
.attr("y1", function(d) { return yScale(d.y1); })
.attr("x2", function(d) { return xScale(d.x2); })
.attr("y2", function(d) { return yScale(d.y2); });
}
有人告诉我这是不可能的.也许有办法?还有,如果我想用鼠标单击将其删除,该如何访问然后从dataset_a行?
I was told it's impossible. Or maybe there is the way? And also how to access then line from dataset_a if i want to delete it with the click of the mouse?
推荐答案
好吧,如果您想绘制线条,建议您附加... <line>
s!
Well, if you want to plot lines, I suggest that you append...<line>
s!
具有D3输入选择的内容非常简单:附加元素的数量是数据数组中与任何元素都不匹配的对象的数量.
The thing with a D3 enter selection is quite simple: the number of appended elements is the number of objects in the data array that doesn't match any element.
因此,您只需要一个包含多个对象的数据数组.例如,让我们创建其中的50个:
So, you just need a data array with several objects. For instance, let's create 50 of them:
var data = d3.range(50).map(function(d) {
return {
x1: Math.random() * 300,
x2: Math.random() * 300,
y1: Math.random() * 150,
y2: Math.random() * 150,
}
});
并且,正如下面的演示中一样,我选择null
,所有这些都将在回车选择中.这是演示:
And, as in the below demo I'm selecting null
, all of them will be in the enter selection. Here is the demo:
var svg = d3.select("svg");
var data = d3.range(50).map(function(d) {
return {
x1: Math.random() * 300,
x2: Math.random() * 300,
y1: Math.random() * 150,
y2: Math.random() * 150,
}
});
var color = d3.scaleOrdinal(d3.schemeCategory20);
var lines = svg.selectAll(null)
.data(data)
.enter()
.append("line")
.attr("x1", function(d) {
return d.x1
})
.attr("x2", function(d) {
return d.x2
})
.attr("y1", function(d) {
return d.y1
})
.attr("y2", function(d) {
return d.y2
})
.style("stroke", function(_, i) {
return color(i)
})
.style("stroke-width", 1);
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg></svg>
最后一个提示:由于这是JavaScript,因此您可以在任意位置使用for
循环.但是,请勿使用for
循环在D3代码中附加元素.这是不必要的,不是惯用的.
Finally, a tip: as this is JavaScript you can use for
loops anywhere you want. However, do not use for
loops to append elements in a D3 code. It's unnecessary and not idiomatic.
话虽这么说,无论谁告诉你这是不可能都是错的,这显然是可能的.这是一个演示(但不要这样做,这是一个非常麻烦且丑陋的代码):
That being said, whoever told you that it is impossible was wrong, it's clearly possible. Here is a demo (but don't do that, it's a very cumbersome and ugly code):
var svg = d3.select("svg");
var data = d3.range(50).map(function(d, i) {
return {
x1: Math.random() * 300,
x2: Math.random() * 300,
y1: Math.random() * 150,
y2: Math.random() * 150,
id: "id" + i
}
});
var color = d3.scaleOrdinal(d3.schemeCategory20);
for (var i = 0; i < data.length; i++) {
var filteredData = data.filter(function(d) {
return d.id === "id" + i
});
var lines = svg.selectAll(null)
.data(filteredData)
.enter()
.append("line")
.attr("x1", function(d) {
return d.x1
})
.attr("x2", function(d) {
return d.x2
})
.attr("y1", function(d) {
return d.y1
})
.attr("y2", function(d) {
return d.y2
})
.style("stroke", function() {
return color(i)
})
.style("stroke-width", 1);
}
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg></svg>
这篇关于在d3中的for循环中绘制多行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!