我想在我的SVG上添加一些圆圈和一个红线。但是,无论他们附加哪个顺序:我总是在后面。
我该如何将其推向前面?我尝试使用movetofront和z轴属性,但无法修复。
我的暂定:
d3.select("svg")
.append("g")
.attr("id", "chart")
.attr("width", width)
.attr("height", height)
filename = "assets/sources/datafile.csv"
d3.csv(filename, d => dataViz(d));
function dataViz(input_data) {
d3.select("svg")
.selectAll("circle")
.data(input_data)
.enter()
.append("circle")
}
d3.select("#chart")
.append('line')
.attr("id", "avg_line")
.attr("x1", xScale(0))
.attr("y1", yScale(3.75))
.attr("x2", xScale(upper_limit))
.attr("y2", yScale(3.75))
.attr("stroke-width", 5)
.attr("stroke", "red")
,这是d3.json
上一个众所周知的主题的有趣变化!由于d3.json
是异步在加载完成之前不会调用回调。尽管附加行的调用似乎是在附加圆圈后,但实际上将立即执行,即附加圆圈,在任何情况下,将线定位在圆圈下。解决方案是将行内部添加附加圆圈后的回调。
function dataViz(input_data) {
d3.select("svg")
.selectAll("circle")
.data(input_data)
.enter()
.append("circle")
d3.select("#chart") // <-- This should be inside the callback.
.append('line')
.attr("id","avg_line")
.attr("x1", xScale(0))
.attr("y1", yScale(3.75))
.attr("x2", xScale(upper_limit))
.attr("y2", yScale(3.75))
.attr("stroke-width",5)
.attr("stroke","red");
}
另一个错误是您选择要附加到的元素的方式。上面校正的代码将生成以下结构:
<svg>
<g id="chart" width="" height="">
<line id="avg_line" x1="" y1="" x2="" y2="" stroke-width="5" stroke="red"></line>
</g>
<circle></circle>
</svg>
这是因为您首先将<g id="chart">
附加到仅附加该行的<svg>
上。另一方面,圆圈将附加到<svg>
本身上。看着那个结构,它变得很明显,为什么线仍然位于圆形后面。
鉴于您尚未提供完整的代码,我无法确定最好的解决方案是什么。但是,由于<g>
只是一个容器元素,它没有width
和height
属性,因此第一个语句应抛弃.append("g")
。另一方面,由于 svg
是您要附加到的元素,因此要对其进行引用,这是很好的做法,这也使您无法反复重新选择相同的元素:
var svg = d3.select("svg") // Keep the reference to the <svg> for later use.
.attr("id", "chart")
.attr("width",width)
.attr("height",height);
在您的回调中,您可以使用此引用以所需的顺序附加元素。将所有这些放在一起,您最终会得到以下内容:
var svg = d3.select("svg")
.attr("id", "chart")
.attr("width",width)
.attr("height",height);
filename="assets/sources/datafile.csv"
d3.csv(filename, dataViz);
function dataViz(input_data) {
svg.selectAll("circle")
.data(input_data)
.enter()
.append("circle")
svg.append('line')
.attr("id","avg_line")
.attr("x1", xScale(0))
.attr("y1", yScale(3.75))
.attr("x2", xScale(upper_limit))
.attr("y2", yScale(3.75))
.attr("stroke-width",5)
.attr("stroke","red");
}
生成的SVG结构看起来如下,将线路上方呈现:
:<svg id="chart" width="" height="">
<circle></circle>
<line id="avg_line" x1="" y1="" x2="" y2="" stroke-width="5" stroke="red"></line>
</svg>
Protip 与您的问题无关:
注意,我如何简化您对d3.csv()
的呼叫。以下两个陈述基本上是等效的(嗯,在我受到惩罚之前,这不是 true,而是在一阶近似中):
d3.csv(filename, d => dataViz(d));
d3.csv(filename, dataViz);
无需将您的功能dataViz()
包装在另一个匿名箭头函数中;只需通过参考它,D3就会照顾它。