如果你只添加一次svg对象,网上有很多案例如何在d3中绘制几行,例如
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); });
此图创建一行。我想在数组smth中创建许多不同的行,如
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访问然后行?
答案 0 :(得分:2)
好吧,如果你想绘制线条,我建议你追加...... <line>
s!
具有D3输入选择的东西非常简单:附加元素的数量是数据数组中与任何元素都不匹配的对象数。
因此,您只需要一个包含多个对象的数据数组。例如,让我们创建50个:
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
,所有这些都将在输入选择中。这是演示:
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代码中追加元素。这是不必要的,而不是惯用的。
话虽如此,无论谁告诉你这是不可能错了,显然是可能的。这是一个演示(但不要这样做,这是一个非常麻烦和丑陋的代码):
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>
答案 1 :(得分:1)
我会做这样的事情。制作每个数据集(每行1个数据集),an array inside the final data array .enter().append()
将正常工作。要在点击时删除该行,我添加了一个事件处理程序,它将选择刚刚单击的行并将其删除。
var data = [[dataset_a], [dataset_b], [dataset_c], [dataset_d], [dataset_e]];
var xValue = function(d){return d.x;}
var yValue = function(d){return d.y;}
var lineFunction = d3.line()
.x(function(d) { return xScale(xValue(d)); })
.y(function(d) { return yScale(yValue(d)); });
var lines = d3.select("svg").selectAll("path")
lines.data(data)
.enter().append("path")
.attr("d", lineFunction)
.on("click", function(d){
d3.select(this).remove();
});