在 Angular 10 中使用 chart.js 创建多个动态堆叠图表?

Create multiple dynamic stacked chart using chart.js in Angular 10?

我正在尝试在 angular 中创建多个图表,但我不确定我尝试实施的方式是否正确,而且我无法创建多个图表并将一个图表替换为另一个图表

 <div *ngIf="chartData.length !== 0">
      <app-limus-utilisation-chart
      *ngFor="let entity of chartData" [chartdata]="entity"
      ></app-limus-utilisation-chart>
    </div>

ChartComponent.ts

getStackedChart() {
        const canvas: any = document.getElementById('canvas1');
        const ctx = canvas.getContext('2d');
        
        var data = {
          labels: this.chartdata.buyernames,
         
          datasets: [{
            label: 'Utilised Limit',
            data: this.chartdata.utilisedlimitData,
            backgroundColor: '#22aa99'
          }, {
            label: 'Available Limit',
            data: this.chartdata.availablelimit,
            backgroundColor: '#994499'
          }]
        }
    
        chartJsLoaded$.pipe(take(1)).subscribe(() => {
          setTimeout(() => {
            this.myChart = new Chart(ctx, {
              type: 'bar',
              data: data,
              options: {
                tooltips: {
                  mode: 'index',
                  intersect: true,
                  position: 'custom',
                  yAlign: 'bottom'
                },
                scales: {
                  xAxes: [{
                    stacked: true
                  }],
                  yAxes: [{
                    stacked: false,
                    display: false
                  }]
                }
              }
            });
          })
    
        })
      }

我试了两种方法

使用视图子图表未创建,getElementById 图表已创建但第二个图表替换了第一个。但我想要并排放置两个堆叠图表 如何实现这一点

当前图表采用低于 100 个值,但根据我的实际要求,我需要显示 tootip 金额,如 (1000000, 700000) 也是货币格式

像这样我试图实现 https://stackblitz.com/edit/angular-chart-js-j26qhm?file=src%2Fapp%2Fapp.component.html

请多多指教

得到答案后,我取得了一些成就

https://stackblitz.com/edit/angular-chart-js-tyggan

问题是这里的这一行:

    const canvas: any = document.getElementById('canvas1');

您在页面上有多个具有该 ID 的元素(因为您使用了 *ngFor),因此它始终将自身附加到页面上的第一个元素。

您应该使用 Angular 的 built-in @ViewChild.

而不是使用 getElementByID

像这样:

chart.component.html:

<canvas #stackchartcanvas></canvas>

chart.component.ts:

@ViewChild("stackchartcanvas") myCanvas: ElementRef<HTMLCanvasElement>;
....
....
....
getStackedChart() {
    const canvas = this.myCanvas.nativeElement;
}

Stackblitz:https://stackblitz.com/edit/angular-chart-js-kny4en?file=src%2Fapp%2Fchart.component.ts

(此外,在您的原始代码中,this.chartData.push() 运行 每次单击复选框时,即使该复选框为假,但这是一个不同的、不相关的问题,也已修复.)

您可以使用 ViewChild 来引用 html 元素并在您的组件中使用它。我还修改了您的代码中的一些内容以切换图表。

总结:

  1. 使用 ViewChild 访问组件中的 html 元素
  2. 更新了应用程序组件以切换图表,而不是仅仅添加数据
  3. 更新标签以接受点击事件来切换复选框

看看this stackblitz

app.component.html

<label>
  <input type="checkbox" value=1
(change)="chooseEntity($event.target.checked, 1, entityData[0])">
  Microsoft
</label>
<label>
<input type="checkbox" (change)="chooseEntity($event.target.checked, 2, entityData[1])">
  IBM
</label>

<div *ngIf="chartData.length !== 0">
  <app-limus-utilisation-chart *ngFor="let entity of chartData" [chartdata]="entity"></app-limus-utilisation-chart>
</div>

chart.component.html

<div #chartReport>
    <canvas #canvas></canvas>
</div>

chart.component.ts

import {
  Component,
  ElementRef,
  Input,
  OnInit,
  ViewChild,
  ViewEncapsulation
} from "@angular/core";
import { Chart } from "chart.js";

import { OnChanges } from "@angular/core";
@Component({
  selector: "app-limus-utilisation-chart",
  templateUrl: "./chart.component.html",
  encapsulation: ViewEncapsulation.None
})
export class LimusUtilisationChartComponent implements OnInit, OnChanges {
  myChart: Chart;
  @Input() chartdata: any;
  @ViewChild("canvas") stackchartcanvas: ElementRef;

  constructor() {}
  ngOnChanges() {
    this.getStackedChart();
  }

  ngOnInit(): void {
    this.getStackedChart();
  }

  getStackedChart() {
    Chart.Tooltip.positioners.custom = function(elements, position) {
      //debugger;
      return {
        x: position.x,
        y:
          elements[0]._view.base - (elements[0].height() + elements[1].height())
      };
    };

    const canvas: any = this.stackchartcanvas.nativeElement;
    const ctx = canvas.getContext("2d");
    var data = {
      labels: this.chartdata.buyernames,

      datasets: [
        {
          label: "Utilised Limit",
          data: this.chartdata.utilisedlimitData,
          backgroundColor: "#22aa99"
        },
        {
          label: "Available Limit",
          data: this.chartdata.availablelimit,
          backgroundColor: "#994499"
        }
      ]
    };

    setTimeout(() => {
      this.myChart = new Chart(ctx, {
        type: "bar",
        data: data,
        options: {
          tooltips: {
            mode: "index",
            intersect: true,
            position: "custom",
            yAlign: "bottom"
          },
          scales: {
            xAxes: [
              {
                stacked: true
              }
            ],
            yAxes: [
              {
                stacked: false,
                display: false
              }
            ]
          }
        }
      });
    });
  }
}