Chart.js在同一组件中使用Angular创建多个图表

sh7euo9m  于 5个月前  发布在  Chart.js
关注(0)|答案(3)|浏览(95)

我有一个Angular 6项目,其中一个组件获取其parrent传递的tile Object。对于每个tile passend,我想用chart.js生成相同的Chart。我对第一个Chart工作正常,但所有其他Chart都没有渲染。控制台错误代码:Failed to create chart: can't acquire context from the given item
我的tile.component.html

<div *ngIf="tile.type === 'tileImg'">
  <div class="card custom-card"
       routerLinkActive="glowing">
    <img class="card-img-top rounded" src="{{ tile.imgPath }}" alt="Tile image" />
    <div class="card-body">
      <p class=" card-text text-center">{{ tile.name }}</p>
    </div>
  </div>
</div>
<div *ngIf="tile.type === 'tileChart'">
  <div class="card custom-card"
       routerLinkActive="glowing">
    <div>
      <canvas id="canvas">{{ chart }}</canvas>
    </div>
    <div class="card-body">
      <p class=" card-text text-center">{{ tile.name }}</p>
    </div>
  </div>
</div>

字符串
我的tile.component.ts -不要介意评论,只是为了测试目的

import { Component, OnInit, Input } from '@angular/core';
import { Chart } from 'chart.js';

import { Tile } from 'src/app/tile-container/tile/tile.model';
//import { TileChart } from 'src/app/tile-container/tile/tile-chart.model';

@Component({
  selector: 'app-tile',
  templateUrl: './tile.component.html',
  styleUrls: ['./tile.component.css']
})
export class TileComponent implements OnInit {
  @Input() tile: Tile;
  //tileChart: TileChart;
  chart = [];

  constructor() { }

  ngOnInit() {
    //console.log(this.tile);
    //console.log(this.tile.getType());
    //console.log(this.tile.getChartType() + "   " + this.tile.getChartData() + "  " + this.tile.getType().localeCompare('tileChart'));
    //console.log(this.tile.getType() == 'tileChart');
    if (this.tile.getType() == 'tileChart') {
      this.generateChart(this.tile.getChartType(), this.tile.getChartData());
      
    }
  }

  generateChart(chartType: string, chartData: number[]) {
    

    this.chart = new Chart('canvas', {
      type: chartType,
      data: {
        datasets: [{
          data: chartData,
          backgroundColor: ['#F39E01', '#b8bbc1']
        }],
        labels: [
          'Verbrauch diese Woche',
          'Einsparung in kWh'
        ]
      },
      options: {
        legend: {
          display: false,
        },
        rotation: 1.1 * Math.PI,
        circumference: 0.8 * Math.PI
      }
    });
  }

}


和父tile-container.component.html -实际上不需要

<div class="container custom-container">
  <div class="container-heading">
    <h2>{{ tileContainer.name }}</h2>
  </div>
  <hr />
  <div class="row">
    <div class="col text-center"
         *ngFor="let tile of tileContainer.tiles">
      <app-tile      
        [tile]="tile">
      </app-tile>
    </div>
  </div>
</div>


Screnshot from missing charts

已编辑

这是我编辑的打字代码。每个瓷砖都有一个ID,我试图使用它来为每个图表创建一个唯一的ID。

ngOnInit() {
    console.log(this.tile.id);
    if (this.tile.getType() == 'tileChart') {
      this.chartId = this.tile.id.toString();
      this.ctx = document.getElementById(this.chartId);
      console.log(this.ctx);
      this.generateChart(this.tile.getChartType(), this.tile.getChartData());
    }
 }


这是我使用数据绑定的html。

<div>
  <p>{{ chartId }}</p>
  <canvas id="{{ chartId }}">{{ chart }}</canvas>
</div>


Picture of error codes

izj3ouym

izj3ouym1#

在模板(html)中,画布的id必须对每个图表不同

vzgqcmou

vzgqcmou2#

我将给予你不同的方法,第一个是最简单的,其他的你需要更多的知识.
1.-你可以生成一个单独的组件来渲染chartjs图形,例如,将其称为chart-dynamic,其中有几个输入id用于抓取渲染几个图表所需的唯一id,以及dataChart用于渲染所有完整的对象,假设你的tile。
很重要!你的dataChart必须像一个对象数组一样思考,每个对象基本上都是一个图表,你将渲染到你的模板中(遵循chartJ的官方文档)

<div *ngIf="tile.type === 'tileImg'">
  <div class="card custom-card"
       routerLinkActive="glowing">
    <img class="card-img-top rounded" src="{{ tile.imgPath }}" alt="Tile image" />
    <div class="card-body">
      <p class=" card-text text-center">{{ tile.name }}</p>
    </div>
  </div>
</div>
<div *ngIf="tile.type === 'tileChart'">
  <div class="card custom-card"
       routerLinkActive="glowing">
<!-- NEW CODE -->

<ng-container *ngIf="dataChart?.length > 0" >
<div *ngFor="let chart of dataChart; let i=index">
    <app-chart-dynamic [id]="SomeUniqueID" [dataChart]="chart" [type]="chart.type"></app-chart-dynamic>
</div>
</ng-container>

<!-- Finish here -->
    <div class="card-body">
      <p class=" card-text text-center">{{ tile.name }}</p>
    </div>
  </div>
</div>

字符串
在你的tile.component.ts中,将generateChart函数移动到新的组件中

import { Component, OnInit, Input } from '@angular/core';
import { Chart } from 'chart.js';

import { Tile } from 'src/app/tile-container/tile/tile.model';
//import { TileChart } from 'src/app/tile-container/tile/tile-chart.model';

@Component({
  selector: 'app-tile',
  templateUrl: './tile.component.html',
  styleUrls: ['./tile.component.css']
})
export class TileComponent implements OnInit {
  @Input() tile: Tile;
  //tileChart: TileChart;
  chart = [];
  public dataChart: [];

  constructor() { }

  ngOnInit() {
    //console.log(this.tile);
    //console.log(this.tile.getType());
    //console.log(this.tile.getChartType() + "   " + this.tile.getChartData() + "  " + this.tile.getType().localeCompare('tileChart'));
    //console.log(this.tile.getType() == 'tileChart');
    this.getCharts();
  }

  public getCharts() { 
    // call data from you service or data mock
    this.dataChart = {....response};
  }

}


现在假设你已经创建了你的新组件,应该是这样的(你已经导入了charJ和其他东西)

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

@Component({
  selector: 'app-chart-dynamic',
  templateUrl: './chart-dynamic.component.html',
  styleUrls: ['./chart-dynamic.component.css']
})
export class ChartDynamic implements OnInit, AfterViewInit {

  @Input() datasChart: any;
  @Input() id: string;
  @Input() type?: string;
  public idChart: any;
  @ViewChild('chart') chart: ElementRef;
  public chartObject: any;

  constructor() { }

  ngOnInit() {

  }

  generateChart(id: string ,chartType?: string, chartData: any) {
    this.idChart = this.id;
    this.chart = new Chart(`${this.idChart}`,  this.datasChart );
  }

  ngAfterViewInit() {
    this.drawGraphics();
  }

}


app-chart-dynamic html文件

<div class="some-class-style" >
    <canvas [id]="id" #chart> {{ chart }}</canvas>
</div>


它应该工作,如果你添加到你的模块等

另一种方法是将合并viewChild和viewChildren与工厂解析器结合起来,它更复杂,但功能更强大,您应该根据Angular 文档检查firts

unftdfkk

unftdfkk3#

index. html

<h5 class="mb-2">Bar Chart</h5>
  <div style="width: 90%" class="mb-4">
    <canvas id="bar-chart">{{ barChart }}</canvas>
  </div>
  <h5 class="mb-2">Line Chart</h5>
  <div style="width: 90%" class="mb-4">
    <canvas id="line-chart">{{ lineChart }}</canvas>
  </div>

字符串
重要的是,当你初始化你的变量(这里是'barChart'和'lineChart'),你可以使用任何,但在TS中,我们想输入一切,所以遵循这两行,正确输入的方式

YOUR_COMPONENT_NAME.ts

import { Component, OnInit } from '@angular/core';
import chartjs from 'chart.js/auto'

export class YOUR_COMPONENT_NAME implements OnInit {
  public barChart: chartjs<"bar", string[], string> | null = null;
  public lineChart: chartjs<"line", string[], string> | null = null;

  constructor() {}

  ngOnInit(): void {
    this.createChart()
  }

  public createChart() {
    this.barChart = new chartjs('bar-chart', {
      type: 'bar', 
      data: {
        labels: ['S1', 'S2', 'S3', 'S4',
          'S5', 'S6', 'S7'],
        datasets: [
          {
            label: "Entrainement",
            data: ['3', '3', '3', '2', '4', '4','3'],
            backgroundColor: '#C72864'
          },
          {
            label: "Alimentation",
            data: ['4', '2', '7', '4', '1', '5','7'],
            backgroundColor: '#157E39'
          }
        ]
      },
      options: {
        aspectRatio: 2.5,
        responsive:true,
        scales: {
          y: {
            title: {
              display:true,
              text:'Jours réusis',
              align: 'end',
            }

          },
          x: {
            position: 'right',
            title: {
              display:true,
              text:'N° semaine',
              align: 'end'
            }
          },
        }
      }
    });
    this.lineChart = new chartjs("line-chart", {
      type: 'line', 
      data: {
        labels: ['S1', 'S2', 'S3', 'S4',
          'S5', 'S6', 'S7', 'S8'],
        datasets: [
          {
            label: "poids",
            data: ['75', '90', '85', '77', '80', '55','75', '65'],
            borderColor: 'blue'
          },
          {
            label: "Tour de cuisses",
            data: ['52', '74', '65', '75', '40', '90','85', '77'],
            backgroundColor: 'limegreen'
          },
          {
            label: "Tour de d'épaules",
            data: ['80', '76', '28', '28', '65', '24','80', '76'],
            backgroundColor: 'limegreen'
          },
          {
            label: "Tour de bras",
            data: ['52', '74', '65', '75', '40', '90','85', '77'],
            backgroundColor: 'limegreen'
          }
        ]
      },
      options: {
        aspectRatio: 2.5,
        responsive:true,
      }
    });
  }
}

相关问题