D3-将条形添加到组

时间:2019-01-09 11:19:55

标签: d3.js

我这里有个突如其来的飞车-https://stackblitz.com/edit/chart-update-1-34uvdo?file=src/app/bar-chart.ts

这是一个有角度的应用程序中的d3图表。

这些条带有箭头,以显示条的开始和结束位置。

我希望每个条形箭头组合都包含在一个g元素中-目前它们都在同一个g元素中。

如何为每个长条和箭头添加一个g元素。

bar.enter()
    .append("line")
    .attr("x1", d => this.x(d.phase) + this.x.bandwidth() / 2)
    .attr("y1", d => this.y(d.start) + ((d.start < d.finish) ? -5 : 5))
    .attr("x2", d => this.x(d.phase) + this.x.bandwidth() / 2)
    .attr("y2", d => this.y(d.finish) + ((d.start < d.finish) ? 5 : -5))
    .attr("stroke", "black")
    .attr("stroke-width", 3)
    .attr("marker-end", "url(#arrow)")
    .style('pointer-events', 'none'); 

1 个答案:

答案 0 :(得分:1)

再次查看d3 general update pattern。这是d3概念中的一个总是让人有些困惑,尤其是将其应用于除最简单的示例以外的任何内容时。

因此,通过查看上述模式,我们可以将其分解为:

  • 数据联接
      

    使用旧元素加入新数据(如果有)。

  • 更新
      

    根据需要更新旧元素。

  • 输入
      

    根据需要创建新元素。

  • 输入+更新
      

    将输入的元素与更新选择合并后,对两者都应用操作。

  • 退出
      

    根据需要删除旧元素。


private drawUpdate(data) {
  this.x.domain(data.map((d: any) => {
    return d.phase
  }));

  this.getExtent(data);

  this.y.domain(d3.extent(this.values));

  this.createAxis();

  // Data Join
  const bar = this.chart.selectAll(".bargroup")
    .data(data);

  // Updates
  // Update rect dimensions
  bar.select('rect').attr("x", (d, i) => {
    return this.x(d.phase)
  })
    .attr("width", (d, i) => {
      return this.x.bandwidth()
    })
    .attr("y", (d, i) => {
      if (d.start < d.finish) {
        return this.y(d.finish);
      } else {
        return this.y(d.start);
      }
    })
    .attr("height", (d, i) => {
      if (d.start < d.finish) {
        return this.y(d.start) - this.y(d.finish);
      } else {
        return this.y(d.finish) - this.y(d.start);
      }
    })

  // Update line dimensions
  bar.select('line')
    .attr("x1", d => this.x(d.phase) + this.x.bandwidth() / 2)
    .attr("y1", d => this.y(d.start) + ((d.start < d.finish) ? -5 : 5))
    .attr("x2", d => this.x(d.phase) + this.x.bandwidth() / 2)
    .attr("y2", d => this.y(d.finish) + ((d.start < d.finish) ? 5 : -5))

  // Enter
  const barEnter = bar.enter()
    .append("g")
    .classed('bargroup', true)

  // Enter & update - append new rects, update dimensions
  barEnter
    .append('rect')
    .attr("x", (d, i) => {
      return this.x(d.phase)
    })
    .attr("width", (d, i) => {
      return this.x.bandwidth()
    })
    .attr("y", (d, i) => {
      if (d.start < d.finish) {
        return this.y(d.finish);
      } else {
        return this.y(d.start);
      }
    })
    .attr("height", (d, i) => {
      if (d.start < d.finish) {
        return this.y(d.start) - this.y(d.finish);
      } else {
        return this.y(d.finish) - this.y(d.start);
      }
    })

  // Enter & update - append new lines, update dimensions
  barEnter
    .append("line")
    .attr("stroke", "white")
    .attr("stroke-width", 3)
    .attr("marker-end", "url(#arrow)")
    .style('pointer-events', 'none')
    .attr("x1", d => this.x(d.phase) + this.x.bandwidth() / 2)
    .attr("y1", d => this.y(d.start) + ((d.start < d.finish) ? -5 : 5))
    .attr("x2", d => this.x(d.phase) + this.x.bandwidth() / 2)
    .attr("y2", d => this.y(d.finish) + ((d.start < d.finish) ? 5 : -5))

  //Exit
  bar.exit()
    .remove();

  d3.select('.y-axis').call(this.y_axis)

  d3.select('.x-axis').call(this.x_axis)
    .attr("transform", "translate(0," + this.height + ")");

}

Updated stackblitz