无法在 table 个单元格中呈现 d3 图表

Unable to render d3 chart in table cells

目前使用 angular 7 和 d3 v7。 尝试在 table 的每个单元格中渲染面积图(如下图所示)。但是使用 angular 方法渲染的 svg 保持循环渲染。不确定我在这里做错了什么

HTML代码

<tr [id]="'row' + '-' + fleet" *ngFor="let fleet of fleetcolumn">
      <td>{{ fleet }}</td>
      <ng-container *ngFor="let station of formattedBaseStations | slice: 1">
        <td style="width: 28em;">
              <div [id]="'demandChartInTable1-' + station + '-' + fleet + '-A'"> {{d3DemandChartIntable(station, fleet, 'A')}} </div>
            </mat-grid-tile>
            <mat-grid-tile class="FOChart">
              <div [id]="'demandChartInTable1-' + station + '-' + fleet + '-B'"> {{d3DemandChartIntable(station, fleet, 'A')}} </div>
            </mat-grid-tile>
          </mat-grid-list>
        </td>
      </ng-container>
    </tr> 

.ts代码

    d3DemandChartIntable(station, code, position) {
    // set data
    let temp1 = this.data
      .filter(d => d.baseCode == station && d.code == code && d.position == position)
      .map(d => {
        return {
          date: d3.timeParse('%Y-%m-%d')(d.date),
          hours: d.hours
        };
      });
    const e = document.querySelector('.captainChart');
    // set the dimensions and margins of the graph
    const margin = { top: 0, right: 0, bottom: 1, left: 1 },
      width = 120 - margin.left - margin.right,
      height = 90 - margin.top - margin.bottom;

    // append the svg object to the body of the page
    const svg = d3
      .select(`#demandChartInTable1-${station}-${fleet}-${position}`)
      .append('svg')
      .attr('width', e.clientWidth + margin.left + margin.right)
      .attr('height', e.clientHeight + margin.bottom)
      .append('g')
      .attr('transform', `translate(${margin.left},${margin.top})`);

    const x = d3
      .scaleTime()
      .domain(d3.extent(data, d => d.date))
      .range([0, e.clientWidth]);

    // Y axis
    const y = d3
      .scaleLinear()
      .domain([0, 500])
      .range([e.clientHeight + margin.bottom, 0]);

    // Add the area
    return svg
      .append('path')
      .datum(temp1)
      .attr('fill', '#cce5df')
      .attr('stroke', '#69b3a2')
      .attr('stroke-width', 1.5)
      .attr(
        'd',
        d3
          .area()
          .x(d => x(d.date))
          .y0(y(0))
          .y1(d => y(d.hours))
      );
  }

以上代码在每个单元格中渲染重复的 svg 而不是只渲染一次

任何帮助将不胜感激

症结在下面的代码中:

const svg = d3
      .select(`#demandChartInTable1-${station}-${fleet}-${position}`)
      .append('svg')

它选择 table 单元格,然后附加一个 SVG 元素。这意味着如果 SVG 已经存在,则会在其旁边添加另一个。如果你想解决这个问题,你可以

  • Select 并更新现有的 SVG 并且只创建一次(例如 ngOnInitngAfterViewInit);
  • 删除任何现有的 SVG 并绘制一个新的,使用
const cell = d3.select(`#demandChartInTable1-${station}-${fleet}-${position}`);
cell.remove('*');
const svg = cell.append('svg')