7

是否可以动态更新任何chart内容ng2-charts?我知道还有其他类似的库angular2-highcharts,但我想使用ng2-charts. chart主要问题是单击按钮后如何重绘?我可以调整窗口大小并且数据将被更新,因此它必须是手动执行的任何选项。

https://plnkr.co/edit/fXQTIjONhzeMDYmAWTe1?p=preview

4

6 回答 6

8

一个好方法是掌握图表本身,以便使用 API 重新绘制它:

export class MyClass {
 @ViewChild( BaseChartDirective ) chart: BaseChartDirective;

  private updateChart(){
   this.chart.ngOnChanges({});
  }

}
于 2016-10-29T12:33:30.033 回答
6

我想通了,也许它不是现有的最佳选择,但它确实有效。我们不能更新现有的chart,但我们可以创建新的,使用我们现有的chart并添加新的点。我们甚至可以得到更好的效果,关闭图表的动画。

解决问题的功能:

updateChart(){
   let _dataSets:Array<any> = new Array(this.datasets.length);
   for (let i = 0; i < this.datasets.length; i++) {
      _dataSets[i] = {data: new Array(this.datasets[i].data.length), label: this.datasets[i].label};
      for (let j = 0; j < this.datasets[i].data.length; j++) {
        _dataSets[i].data[j] = this.datasets[i].data[j];
      }
   }
   this.datasets = _dataSets;
}

现场演示:https ://plnkr.co/edit/fXQTIjONhzeMDYmAWTe1?p=preview

@UPDATE: 正如@Raydelto Hernandez 在下面的评论中提到的,更好的解决方案是:

updateChart(){
    this.datasets = this.dataset.slice()
}
于 2016-08-23T10:09:15.220 回答
5

最近我不得不使用 ng2-charts,在我找到这个解决方案之前,我在更新数据方面遇到了很大的问题:

<div class="chart">
        <canvas baseChart [datasets]="datasets_lines" [labels]="labels_line" [colors]="chartColors" [options]="options" [chartType]="lineChartType">
        </canvas>
</div>

这里是我的组件中的内容:

import { Component, OnInit, Pipe, ViewChild, ElementRef } from '@angular/core';
import { BaseChartDirective } from 'ng2-charts/ng2-charts';

@Component({
    moduleId: module.id,
    selector: 'product-detail',
    templateUrl: 'product-detail.component.html'
})

export class ProductDetailComponent {
    @ViewChild(BaseChartDirective) chart: BaseChartDirective;

    private datasets_lines: { label: string, backgroundColor: string, borderColor: string, data: Array<any> }[] = [
        {
            label: "Quantities",
            data: Array<any>()
        }
    ];

    private labels_line = Array<any>();

    private options = {
        scales: {
            yAxes: [{
                ticks: {
                    beginAtZero: true
                }
            }]
        }
    };


    constructor() { }
    ngOnInit() {

        this.getStats();

    }
    getStats() {

        this.labels_line = this.getDates();

        this._statsService.getStatistics(this.startDate, this.endDate, 'comparaison')
            .subscribe(
            res => {
                console.log('getStats success');
                this.stats = res;

                this.datasets_lines = [];

                let arr: any[];
                arr = [];
                for (let stat of this.stats) {
                    arr.push(stat.quantity);
                }

                this.datasets_lines.push({
                    label: 'title',
                    data: arr
                });

                this.refresh_chart();

            },
            err => {
                console.log("getStats failed from component");
            },
            () => {
                console.log('getStats finished');
            });
    }

    refresh_chart() {
        setTimeout(() => {
            console.log(this.datasets_lines_copy);
            console.log(this.datasets_lines);
            if (this.chart && this.chart.chart && this.chart.chart.config) {
                this.chart.chart.config.data.labels = this.labels_line;
                this.chart.chart.config.data.datasets = this.datasets_lines;
                this.chart.chart.update();
            }
        });
    }

    getDates() {
        let dateArray: string[] = [];
        let currentDate: Date = new Date();
        currentDate.setTime(this.startDate.getTime());
        let pushed: string;
        for (let i = 1; i < this.daysNum; i++) {
            pushed = currentDate == null ? '' : this._datePipe.transform(currentDate, 'dd/MM/yyyy');
            dateArray.push(pushed);
            currentDate.setTime(currentDate.getTime() + 24 * 60 * 60 * 1000);
        }
        return dateArray;
    }    
}

我确信这是正确的方法。

于 2017-03-09T10:04:43.780 回答
4

**这对我有用 - 使用饼图:*

组件.html:

 <canvas baseChart [colors]="chartColors" [data]="pieChartData" [labels]="pieChartLabels" [chartType]="pieChartType"></canvas>

组件.ts:

在标题部分:

import { Component, OnInit, ViewChild, ElementRef } from '@angular/core';
import { Chart } from 'chart.js';
import { BaseChartDirective } from 'ng2-charts/ng2-charts';

在出口类的申​​报部分:

@ViewChild(BaseChartDirective) chart: BaseChartDirective;
// for custom colors
public chartColors: Array<any> = [{
backgroundColor: ['rgb(87, 111, 158)', 'yellow', 'pink', 'rgb(102, 151, 185)'],
borderColor: ['white', 'white', 'white', 'white']
}];

在更新您的饼图数据的块之后(使用服务/套接字或任何其他方式):

this.chart.chart.update();
于 2018-01-03T07:21:39.977 回答
4

这是在 2020 年,其中存在ng2-charts的示意图

npm i ng2-charts
ng generate ng2-charts-schematics:<type> <chart-name>

这会生成一个组件(例如,名为 times-bought 的条形图)

times-bought.component.html

<div style="display: block; width: 40vw; height:80vh">
  <canvas baseChart
    [datasets]="barChartData"
    [labels]="barChartLabels"
    [options]="barChartOptions"
    [colors]="barChartColors"
    [legend]="barChartLegend"
    [chartType]="barChartType"
    [plugins]="barChartPlugins">
  </canvas>
</div>

并且在组件 ts 中,您订阅了一个服务,该服务返回一个可观察的数据,在这种情况下,我们计算一个 firestore 字段值,我们将其解析为一个数字和购买的课程/产品的标题

times-bought.component.ts

import { Component, OnInit } from '@angular/core';
import { ChartDataSets, ChartOptions, ChartType } from 'chart.js';
import { Color, Label } from 'ng2-charts';
import { AdminService } from 'src/app/services/admin.service';
import { _COURSES, _BAR_CHART_COLORS } from  "../../../../settings/courses.config";//

@Component({
 selector: 'times-bought-chart', // Name this however you want
 templateUrl: './times-bought.component.html', 
 styleUrls: ['./times-bought.component.scss']
})
export class TimesBoughtComponent implements OnInit {

public barChartData: ChartDataSets[] = [
 { data: [0, 0, 0, 0], label: 'Times Bought', barThickness: 60, barPercentage: 0.1 }];
public barChartLabels: Label[] = _COURSES  // Array of strings
public barChartOptions: ChartOptions = {
  responsive: true,
  scales: { yAxes: [{ ticks: { beginAtZero: true } }] }
};
public barChartColors: Color[] = _BAR_CHART_COLORS // 
public barChartLegend = true;
public barChartType: ChartType = 'bar';
public barChartPlugins = [];

constructor(private adminService: AdminService) { }

ngOnInit() {
  this.adminService.getAllCourses().subscribe(
    data =>{
      this.barChartData[0].data = data.map(v=> parseInt((v.times_bought).toString())) // parse FieldValue to Int
      this.barChartLabels = data.map(v => v.title)
  })
}}

对 firestore 执行实际查询并返回 observable 的服务 ts 文件

import { Injectable } from '@angular/core';
import { AngularFirestore } from '@angular/fire/firestore';
import { Course } from '../interfaces/course.interface';

@Injectable({
  providedIn: 'root'
})
export class AdminService {

constructor(private db: AngularFirestore) { }

public  getAllCourses(){
  return this.db.collection<Course>('courses', ref =>
    ref.orderBy('times_bought', 'desc')).valueChanges()
}}

和 settings/courses.config.ts

export const _COURSES = [
 'Title1',
 'Title2',
 'Title3',
 'Title4']

 export const _BAR_CHART_COLORS = [
 {
   borderColor: [
     'rgba(255,0,0,0.5)',
     'rgba(54, 75, 181, 0.5)',
     'rgba(114, 155, 59, 0.5)',
     'rgba(102, 59, 155, 0.5)'
   ],
   backgroundColor: [
     'rgba(255,0,0,0.3)',
     'rgba(54, 75, 181, 0.3)',
     'rgba(114, 155, 59, 0.3)',
     'rgba(102, 59, 155, 0.3)'
   ]
 }]

还要确保在 ngOnDestroy 中关闭订阅。每次更新 times_bought 字段时,课程集合的 observable 都会发出一个新值,这将触发图表中的更新。唯一的缺点是颜色绑定到特定的列/栏,所以如果一个标题超过另一个,只有标题会改变位置,y轴会相应更新,但颜色不会更新另外确保你包括 node_modules/dist/ Chart.min.js 到您的 Web 清单(在 pwa 服务工作者的情况下),或作为 index.html 中的脚本

于 2020-11-11T19:55:02.587 回答
1

可以动态更新任何图表ng2-charts。示例: http ://plnkr.co/edit/m3fBiHpKuDgYG6GVdJQD?p=preview

Angular 更新图表、变量或引用必须更改。当您仅更改数组元素的值时,变量和引用不会更改。 另请参阅 Github

于 2016-08-29T19:20:02.717 回答