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

sh7euo9m  于 2021-07-29  发布在  Chart.js
关注(0)|答案(3)|浏览(289)

我有一个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

  1. <div *ngIf="tile.type === 'tileImg'">
  2. <div class="card custom-card"
  3. routerLinkActive="glowing">
  4. <img class="card-img-top rounded" src="{{ tile.imgPath }}" alt="Tile image" />
  5. <div class="card-body">
  6. <p class=" card-text text-center">{{ tile.name }}</p>
  7. </div>
  8. </div>
  9. </div>
  10. <div *ngIf="tile.type === 'tileChart'">
  11. <div class="card custom-card"
  12. routerLinkActive="glowing">
  13. <div>
  14. <canvas id="canvas">{{ chart }}</canvas>
  15. </div>
  16. <div class="card-body">
  17. <p class=" card-text text-center">{{ tile.name }}</p>
  18. </div>
  19. </div>
  20. </div>

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

  1. import { Component, OnInit, Input } from '@angular/core';
  2. import { Chart } from 'chart.js';
  3. import { Tile } from 'src/app/tile-container/tile/tile.model';
  4. //import { TileChart } from 'src/app/tile-container/tile/tile-chart.model';
  5. @Component({
  6. selector: 'app-tile',
  7. templateUrl: './tile.component.html',
  8. styleUrls: ['./tile.component.css']
  9. })
  10. export class TileComponent implements OnInit {
  11. @Input() tile: Tile;
  12. //tileChart: TileChart;
  13. chart = [];
  14. constructor() { }
  15. ngOnInit() {
  16. //console.log(this.tile);
  17. //console.log(this.tile.getType());
  18. //console.log(this.tile.getChartType() + " " + this.tile.getChartData() + " " + this.tile.getType().localeCompare('tileChart'));
  19. //console.log(this.tile.getType() == 'tileChart');
  20. if (this.tile.getType() == 'tileChart') {
  21. this.generateChart(this.tile.getChartType(), this.tile.getChartData());
  22. }
  23. }
  24. generateChart(chartType: string, chartData: number[]) {
  25. this.chart = new Chart('canvas', {
  26. type: chartType,
  27. data: {
  28. datasets: [{
  29. data: chartData,
  30. backgroundColor: ['#F39E01', '#b8bbc1']
  31. }],
  32. labels: [
  33. 'Verbrauch diese Woche',
  34. 'Einsparung in kWh'
  35. ]
  36. },
  37. options: {
  38. legend: {
  39. display: false,
  40. },
  41. rotation: 1.1 * Math.PI,
  42. circumference: 0.8 * Math.PI
  43. }
  44. });
  45. }
  46. }


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

  1. <div class="container custom-container">
  2. <div class="container-heading">
  3. <h2>{{ tileContainer.name }}</h2>
  4. </div>
  5. <hr />
  6. <div class="row">
  7. <div class="col text-center"
  8. *ngFor="let tile of tileContainer.tiles">
  9. <app-tile
  10. [tile]="tile">
  11. </app-tile>
  12. </div>
  13. </div>
  14. </div>


Screnshot from missing charts

已编辑

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

  1. ngOnInit() {
  2. console.log(this.tile.id);
  3. if (this.tile.getType() == 'tileChart') {
  4. this.chartId = this.tile.id.toString();
  5. this.ctx = document.getElementById(this.chartId);
  6. console.log(this.ctx);
  7. this.generateChart(this.tile.getChartType(), this.tile.getChartData());
  8. }
  9. }


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

  1. <div>
  2. <p>{{ chartId }}</p>
  3. <canvas id="{{ chartId }}">{{ chart }}</canvas>
  4. </div>


Picture of error codes

izj3ouym

izj3ouym1#

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

vzgqcmou

vzgqcmou2#

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

  1. <div *ngIf="tile.type === 'tileImg'">
  2. <div class="card custom-card"
  3. routerLinkActive="glowing">
  4. <img class="card-img-top rounded" src="{{ tile.imgPath }}" alt="Tile image" />
  5. <div class="card-body">
  6. <p class=" card-text text-center">{{ tile.name }}</p>
  7. </div>
  8. </div>
  9. </div>
  10. <div *ngIf="tile.type === 'tileChart'">
  11. <div class="card custom-card"
  12. routerLinkActive="glowing">
  13. <!-- NEW CODE -->
  14. <ng-container *ngIf="dataChart?.length > 0" >
  15. <div *ngFor="let chart of dataChart; let i=index">
  16. <app-chart-dynamic [id]="SomeUniqueID" [dataChart]="chart" [type]="chart.type"></app-chart-dynamic>
  17. </div>
  18. </ng-container>
  19. <!-- Finish here -->
  20. <div class="card-body">
  21. <p class=" card-text text-center">{{ tile.name }}</p>
  22. </div>
  23. </div>
  24. </div>

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

  1. import { Component, OnInit, Input } from '@angular/core';
  2. import { Chart } from 'chart.js';
  3. import { Tile } from 'src/app/tile-container/tile/tile.model';
  4. //import { TileChart } from 'src/app/tile-container/tile/tile-chart.model';
  5. @Component({
  6. selector: 'app-tile',
  7. templateUrl: './tile.component.html',
  8. styleUrls: ['./tile.component.css']
  9. })
  10. export class TileComponent implements OnInit {
  11. @Input() tile: Tile;
  12. //tileChart: TileChart;
  13. chart = [];
  14. public dataChart: [];
  15. constructor() { }
  16. ngOnInit() {
  17. //console.log(this.tile);
  18. //console.log(this.tile.getType());
  19. //console.log(this.tile.getChartType() + " " + this.tile.getChartData() + " " + this.tile.getType().localeCompare('tileChart'));
  20. //console.log(this.tile.getType() == 'tileChart');
  21. this.getCharts();
  22. }
  23. public getCharts() {
  24. // call data from you service or data mock
  25. this.dataChart = {....response};
  26. }
  27. }


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

  1. import { Component, OnInit, Input, ViewChild, ElementRef, AfterViewInit } from '@angular/core';
  2. import { Chart } from 'chart.js';
  3. @Component({
  4. selector: 'app-chart-dynamic',
  5. templateUrl: './chart-dynamic.component.html',
  6. styleUrls: ['./chart-dynamic.component.css']
  7. })
  8. export class ChartDynamic implements OnInit, AfterViewInit {
  9. @Input() datasChart: any;
  10. @Input() id: string;
  11. @Input() type?: string;
  12. public idChart: any;
  13. @ViewChild('chart') chart: ElementRef;
  14. public chartObject: any;
  15. constructor() { }
  16. ngOnInit() {
  17. }
  18. generateChart(id: string ,chartType?: string, chartData: any) {
  19. this.idChart = this.id;
  20. this.chart = new Chart(`${this.idChart}`, this.datasChart );
  21. }
  22. ngAfterViewInit() {
  23. this.drawGraphics();
  24. }
  25. }


app-chart-dynamic html文件

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


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

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

展开查看全部
unftdfkk

unftdfkk3#

index. html

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

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

YOUR_COMPONENT_NAME.ts

  1. import { Component, OnInit } from '@angular/core';
  2. import chartjs from 'chart.js/auto'
  3. export class YOUR_COMPONENT_NAME implements OnInit {
  4. public barChart: chartjs<"bar", string[], string> | null = null;
  5. public lineChart: chartjs<"line", string[], string> | null = null;
  6. constructor() {}
  7. ngOnInit(): void {
  8. this.createChart()
  9. }
  10. public createChart() {
  11. this.barChart = new chartjs('bar-chart', {
  12. type: 'bar',
  13. data: {
  14. labels: ['S1', 'S2', 'S3', 'S4',
  15. 'S5', 'S6', 'S7'],
  16. datasets: [
  17. {
  18. label: "Entrainement",
  19. data: ['3', '3', '3', '2', '4', '4','3'],
  20. backgroundColor: '#C72864'
  21. },
  22. {
  23. label: "Alimentation",
  24. data: ['4', '2', '7', '4', '1', '5','7'],
  25. backgroundColor: '#157E39'
  26. }
  27. ]
  28. },
  29. options: {
  30. aspectRatio: 2.5,
  31. responsive:true,
  32. scales: {
  33. y: {
  34. title: {
  35. display:true,
  36. text:'Jours réusis',
  37. align: 'end',
  38. }
  39. },
  40. x: {
  41. position: 'right',
  42. title: {
  43. display:true,
  44. text:'N° semaine',
  45. align: 'end'
  46. }
  47. },
  48. }
  49. }
  50. });
  51. this.lineChart = new chartjs("line-chart", {
  52. type: 'line',
  53. data: {
  54. labels: ['S1', 'S2', 'S3', 'S4',
  55. 'S5', 'S6', 'S7', 'S8'],
  56. datasets: [
  57. {
  58. label: "poids",
  59. data: ['75', '90', '85', '77', '80', '55','75', '65'],
  60. borderColor: 'blue'
  61. },
  62. {
  63. label: "Tour de cuisses",
  64. data: ['52', '74', '65', '75', '40', '90','85', '77'],
  65. backgroundColor: 'limegreen'
  66. },
  67. {
  68. label: "Tour de d'épaules",
  69. data: ['80', '76', '28', '28', '65', '24','80', '76'],
  70. backgroundColor: 'limegreen'
  71. },
  72. {
  73. label: "Tour de bras",
  74. data: ['52', '74', '65', '75', '40', '90','85', '77'],
  75. backgroundColor: 'limegreen'
  76. }
  77. ]
  78. },
  79. options: {
  80. aspectRatio: 2.5,
  81. responsive:true,
  82. }
  83. });
  84. }
  85. }

展开查看全部

相关问题