将SVG线推向前面



我想在我的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>只是一个容器元素,它没有widthheight属性,因此第一个语句应抛弃.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就会照顾它。

最新更新