D3 - Add bars into group

后端 未结 1 1728
陌清茗
陌清茗 2021-01-23 21:44

I have a stackblitz here - https://stackblitz.com/edit/chart-update-1-34uvdo?file=src/app/bar-chart.ts

It\'s a d3 chart in an angular app.

The bars have arrows t

相关标签:
1条回答
  • 2021-01-23 21:58

    Have a look again at the d3 general update pattern. It is one of those d3 concepts that will always be a little confusing, especially when applying it to anything except the simplest examples.

    So by looking at the above pattern we can break it down as:

    • Data Join

      Join new data with old elements, if any.

    • Update

      Update old elements as needed.

    • Enter

      Create new elements as needed.

    • Enter + Update

      After merging the entered elements with the update selection, apply operations to both.

    • Exit

      Remove old elements as needed.


    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

    0 讨论(0)
提交回复
热议问题