动态更新的 ng2-charts
Dynamically updated ng2-charts
是否可以动态更新 ng2-charts
中的任何 chart
?我知道还有其他库,例如 angular2-highcharts
,但我想使用 ng2-charts
来处理它。主要问题是单击按钮后如何重绘 chart
?我可以调整大小 window 并且数据将被更新,所以它必须是手动执行的任何选项。
我明白了,也许它不是现有的最佳选择,但它确实有效。我们无法更新现有 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
@更新:
正如@Raydelto Hernandez 在下面的评论中提到的,更好的解决方案是:
updateChart(){
this.datasets = this.dataset.slice()
}
可以动态更新 ng2-charts
中的任何图表。
例子:
http://plnkr.co/edit/m3fBiHpKuDgYG6GVdJQD?p=preview
Angular 更新图表、变量或引用必须更改。当您仅更改数组元素的值时,变量和引用不会更改。
See also Github.
一个好方法是掌握图表本身,以便使用 API 重新绘制它:
export class MyClass {
@ViewChild( BaseChartDirective ) chart: BaseChartDirective;
private updateChart(){
this.chart.ngOnChanges({});
}
}
最近我不得不使用 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;
}
}
我确定这是正确的方法。
**这对我有用——饼图:*
Component.html:
<canvas baseChart [colors]="chartColors" [data]="pieChartData" [labels]="pieChartLabels" [chartType]="pieChartType"></canvas>
Component.ts:
在页眉部分:
import { Component, OnInit, ViewChild, ElementRef } from '@angular/core';
import { Chart } from 'chart.js';
import { BaseChartDirective } from 'ng2-charts/ng2-charts';
在出口申报部分class:
@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']
}];
在更新饼图数据的块之后(使用 services/sockets 或任何其他方式):
this.chart.chart.update();
这是在 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 中,您订阅了一项服务,该服务 returns 可观察到数据,在这种情况下,我们计算一个 firestore 字段值,我们将其解析为数字和 [=32= 的标题] 买了
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 的实际查询的服务 ts 文件和 returns 可观察的
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 字段时,课程 collection 的可观察值将发出一个新值,这将触发图表中的更新。
唯一的缺点是颜色被绑定到特定的 column/bar 所以如果一个标题超过另一个只有标题会改变位置并且 y-axis 会相应更新但颜色不会
还要确保将 node_modules/dist/Chart.min.js 包含到您的 Web 清单中(如果是 pwa service worker),或者作为 index.html
中的脚本
是否可以动态更新 ng2-charts
中的任何 chart
?我知道还有其他库,例如 angular2-highcharts
,但我想使用 ng2-charts
来处理它。主要问题是单击按钮后如何重绘 chart
?我可以调整大小 window 并且数据将被更新,所以它必须是手动执行的任何选项。
我明白了,也许它不是现有的最佳选择,但它确实有效。我们无法更新现有 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
@更新: 正如@Raydelto Hernandez 在下面的评论中提到的,更好的解决方案是:
updateChart(){
this.datasets = this.dataset.slice()
}
可以动态更新 ng2-charts
中的任何图表。
例子:
http://plnkr.co/edit/m3fBiHpKuDgYG6GVdJQD?p=preview
Angular 更新图表、变量或引用必须更改。当您仅更改数组元素的值时,变量和引用不会更改。 See also Github.
一个好方法是掌握图表本身,以便使用 API 重新绘制它:
export class MyClass {
@ViewChild( BaseChartDirective ) chart: BaseChartDirective;
private updateChart(){
this.chart.ngOnChanges({});
}
}
最近我不得不使用 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;
}
}
我确定这是正确的方法。
**这对我有用——饼图:*
Component.html:
<canvas baseChart [colors]="chartColors" [data]="pieChartData" [labels]="pieChartLabels" [chartType]="pieChartType"></canvas>
Component.ts:
在页眉部分:
import { Component, OnInit, ViewChild, ElementRef } from '@angular/core';
import { Chart } from 'chart.js';
import { BaseChartDirective } from 'ng2-charts/ng2-charts';
在出口申报部分class:
@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']
}];
在更新饼图数据的块之后(使用 services/sockets 或任何其他方式):
this.chart.chart.update();
这是在 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 中,您订阅了一项服务,该服务 returns 可观察到数据,在这种情况下,我们计算一个 firestore 字段值,我们将其解析为数字和 [=32= 的标题] 买了
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 的实际查询的服务 ts 文件和 returns 可观察的
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 字段时,课程 collection 的可观察值将发出一个新值,这将触发图表中的更新。 唯一的缺点是颜色被绑定到特定的 column/bar 所以如果一个标题超过另一个只有标题会改变位置并且 y-axis 会相应更新但颜色不会 还要确保将 node_modules/dist/Chart.min.js 包含到您的 Web 清单中(如果是 pwa service worker),或者作为 index.html
中的脚本