如何在 ng2-chart 中使用 Chart.js 插件数据标签?
How to use Chart.js plugin data-labels with ng2-chart?
好吧,我又遇到了 Angular 和 javascript 的问题,我问的每个问题都让我感到很愚蠢。
但让我试着解释一下我最初的步骤以及它是如何导致这个问题的。因此,在我最新的项目中,我想添加一些花哨的图表,让用户更清楚、更容易理解。 Chart.js 浮现在脑海中......或者我应该说,ng2-charts。
一切都很好,东西看起来不错,但是......我有两个问题。在水平条上,我想动态改变图表的大小,这样用户就不必滚动一段模糊的时间来向下滚动页面。所以而不是这个笨重的野兽...
我尝试应用一些 Angular 魔法。稍后我想在我的后端计算它的大小。现在,应该使用静态值。
@ViewChild('inventoryChart') itemChart : ElementRef;
constructor(public renderer: Renderer2) { }
ngAfterViewInit() {
this.renderer.setStyle(this.itemChart.nativeElement, 'height', '230px')
}
这导致...
不错。 但是我的第二个问题比我想象的要难得多。我希望图表在每个条形图上都有各自的值。我有点震惊地得知,这不是 chart.js 的固有功能,而是一个插件。所以我试图通过查看我的图表配置来缩小我遇到的问题。
@ViewChild('itemChart') itemChart : ElementRef;
//public context: CanvasRenderingContext2D;
public chartType: string = 'horizontalBar';
chartDatalabel: ChartLabel;
public chartDatasets: Array<any> = [
{ data: [28, 20, 6, 5, 3], label: 'Inventory per country' }
];
public chartLabels: Array<any> = ['DEU', 'SVK', 'FRA', 'GBR', 'AUT'];
public chartColors: Array<any> = [
{
backgroundColor: '#0E599A',
pointBackgroundColor: 'rgba(220,220,220,1)',
pointBorderColor: '#fff',
pointHoverBackgroundColor: '#fff',
pointHoverBorderColor: 'rgba(220,220,220,1)'
},
];
public chartOptions: any = {
responsive: true,
maintainAspectRatio: false,
scales: {
yAxes: [{
barPercentage: .9,
categoryPercentage: .9,
gridLines: {
offsetGridLines: true,
display: true,
},
ticks: {
beginAtZero: true
}
}],
xAxes: [{
ticks: {
beginAtZero: true,
min: 0
},
gridLines: {
offsetGridLines: true,
display: true,
},
}]
},
};
由于我有类似的问题,通过查看文档...它需要图表来注册插件。
所以我添加了
import { Chart } from 'chart.js';
但很快意识到,我不知道如何实际获取我在组件中创建的图表实例。我如何才能将它添加到这个特定图表的选项中?我没有找到很多与我有类似问题的来源(这让我觉得更加无能......)。
是否有任何干净的 'angular-way' 可以在 ng2-charts 中添加此插件?
编辑: 从文档来看,我可以通过以下方式定义插件可以做什么...
var plugin = { /* plugin implementation */ };
然后在图表的选项中或全局调用这个插件...
Chart.plugins.register({
// plugin implementation
});
我想避免。除非绝对必要和节省时间,否则永远不要喜欢全局配置。
EDIT2:Sorta 放弃了不在全球范围内注册它,但它仍然无济于事。我添加到我的进口...
import { Chart } from 'chart.js';
import * as ChartLabel from 'chartjs-plugin-datalabels';
然后尝试在全局图表中注册插件。
ngOnInit() {
Chart.plugins.register(ChartLabel);
}
据我所知'something'。所以我试图做一个非常基本的插件实现。其他工具提示不再起作用,但它只会在我将鼠标悬停在栏上时触发错误。
plugins: {
datalabels: {
color: 'white',
display: true,
font: {
weight: 'bold'
},
formatter: Math.round
}
},
不知道我还能做什么...
好吧,由于实际上没有答案,我最终可以接受 "Global" 图表解决方案。
Chart.pluginService.register({
// I gave it an id, so I could disable the plugin if needed
id: 'p1',
afterDatasetsDraw: function (chart, _ease) {
let width = chart.chart.width;
let ctx = chart.chart.ctx;
let datasets = chart.data.datasets;
datasets.forEach(function (_dataset, index) {
let meta = chart.getDatasetMeta(index);
// grabbing the array with the data...
let barLabelData = meta.controller._data;
// console.log(meta.controller._data)
if (!meta.hidden) {
meta.data.forEach(function (segment, _index) {
let model = segment._model;
let position = segment.tooltipPosition();
let x = position.x;
let y = position.y;
let height = model.height;
ctx.restore();
ctx.textBaseline = "middle";
// var fontSize = (height / 114).toFixed(2);
ctx.font = 'bold ' + height / 2 + 'px Arial';
ctx.fillStyle = '#777'; //first label's font color
let text = barLabelData[_index];
ctx.fillText(text, x, y);
ctx.save();
})
}
});
}
});
最终我得到了一张看起来还不错的图表。所以是的,它不像我想要的那样干净。但是执行起来还是有问题。
我的图表组件全局实现了我的插件逻辑。这是糟糕的设计,我必须将它解耦。小问题是,我必须确保标签始终有效并正确描绘。但现在我很高兴它有效。
这是@paviad 做的一个例子:
https://stackblitz.com/edit/ng2-charts-bar-labels
import { Component, OnInit } from '@angular/core';
import { ChartOptions, ChartType, ChartDataSets } from 'chart.js';
import * as pluginDataLabels from 'chartjs-plugin-datalabels';
import { Label } from 'ng2-charts';
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
public barChartOptions: ChartOptions = {
responsive: true,
// We use these empty structures as placeholders for dynamic theming.
scales: { xAxes: [{}], yAxes: [{}] },
plugins: {
datalabels: {
anchor: 'end',
align: 'end',
font: {
size: 20,
}
}
}
};
...
public barChartPlugins = [pluginDataLabels];
...
好吧,我又遇到了 Angular 和 javascript 的问题,我问的每个问题都让我感到很愚蠢。
但让我试着解释一下我最初的步骤以及它是如何导致这个问题的。因此,在我最新的项目中,我想添加一些花哨的图表,让用户更清楚、更容易理解。 Chart.js 浮现在脑海中......或者我应该说,ng2-charts。
一切都很好,东西看起来不错,但是......我有两个问题。在水平条上,我想动态改变图表的大小,这样用户就不必滚动一段模糊的时间来向下滚动页面。所以而不是这个笨重的野兽...
我尝试应用一些 Angular 魔法。稍后我想在我的后端计算它的大小。现在,应该使用静态值。
@ViewChild('inventoryChart') itemChart : ElementRef;
constructor(public renderer: Renderer2) { }
ngAfterViewInit() {
this.renderer.setStyle(this.itemChart.nativeElement, 'height', '230px')
}
这导致...
不错。 但是我的第二个问题比我想象的要难得多。我希望图表在每个条形图上都有各自的值。我有点震惊地得知,这不是 chart.js 的固有功能,而是一个插件。所以我试图通过查看我的图表配置来缩小我遇到的问题。
@ViewChild('itemChart') itemChart : ElementRef;
//public context: CanvasRenderingContext2D;
public chartType: string = 'horizontalBar';
chartDatalabel: ChartLabel;
public chartDatasets: Array<any> = [
{ data: [28, 20, 6, 5, 3], label: 'Inventory per country' }
];
public chartLabels: Array<any> = ['DEU', 'SVK', 'FRA', 'GBR', 'AUT'];
public chartColors: Array<any> = [
{
backgroundColor: '#0E599A',
pointBackgroundColor: 'rgba(220,220,220,1)',
pointBorderColor: '#fff',
pointHoverBackgroundColor: '#fff',
pointHoverBorderColor: 'rgba(220,220,220,1)'
},
];
public chartOptions: any = {
responsive: true,
maintainAspectRatio: false,
scales: {
yAxes: [{
barPercentage: .9,
categoryPercentage: .9,
gridLines: {
offsetGridLines: true,
display: true,
},
ticks: {
beginAtZero: true
}
}],
xAxes: [{
ticks: {
beginAtZero: true,
min: 0
},
gridLines: {
offsetGridLines: true,
display: true,
},
}]
},
};
由于我有类似的问题,通过查看文档...它需要图表来注册插件。
所以我添加了
import { Chart } from 'chart.js';
但很快意识到,我不知道如何实际获取我在组件中创建的图表实例。我如何才能将它添加到这个特定图表的选项中?我没有找到很多与我有类似问题的来源(这让我觉得更加无能......)。
是否有任何干净的 'angular-way' 可以在 ng2-charts 中添加此插件?
编辑: 从文档来看,我可以通过以下方式定义插件可以做什么...
var plugin = { /* plugin implementation */ };
然后在图表的选项中或全局调用这个插件...
Chart.plugins.register({
// plugin implementation
});
我想避免。除非绝对必要和节省时间,否则永远不要喜欢全局配置。
EDIT2:Sorta 放弃了不在全球范围内注册它,但它仍然无济于事。我添加到我的进口...
import { Chart } from 'chart.js';
import * as ChartLabel from 'chartjs-plugin-datalabels';
然后尝试在全局图表中注册插件。
ngOnInit() {
Chart.plugins.register(ChartLabel);
}
据我所知'something'。所以我试图做一个非常基本的插件实现。其他工具提示不再起作用,但它只会在我将鼠标悬停在栏上时触发错误。
plugins: {
datalabels: {
color: 'white',
display: true,
font: {
weight: 'bold'
},
formatter: Math.round
}
},
不知道我还能做什么...
好吧,由于实际上没有答案,我最终可以接受 "Global" 图表解决方案。
Chart.pluginService.register({
// I gave it an id, so I could disable the plugin if needed
id: 'p1',
afterDatasetsDraw: function (chart, _ease) {
let width = chart.chart.width;
let ctx = chart.chart.ctx;
let datasets = chart.data.datasets;
datasets.forEach(function (_dataset, index) {
let meta = chart.getDatasetMeta(index);
// grabbing the array with the data...
let barLabelData = meta.controller._data;
// console.log(meta.controller._data)
if (!meta.hidden) {
meta.data.forEach(function (segment, _index) {
let model = segment._model;
let position = segment.tooltipPosition();
let x = position.x;
let y = position.y;
let height = model.height;
ctx.restore();
ctx.textBaseline = "middle";
// var fontSize = (height / 114).toFixed(2);
ctx.font = 'bold ' + height / 2 + 'px Arial';
ctx.fillStyle = '#777'; //first label's font color
let text = barLabelData[_index];
ctx.fillText(text, x, y);
ctx.save();
})
}
});
}
});
最终我得到了一张看起来还不错的图表。所以是的,它不像我想要的那样干净。但是执行起来还是有问题。
我的图表组件全局实现了我的插件逻辑。这是糟糕的设计,我必须将它解耦。小问题是,我必须确保标签始终有效并正确描绘。但现在我很高兴它有效。
这是@paviad 做的一个例子:
https://stackblitz.com/edit/ng2-charts-bar-labels
import { Component, OnInit } from '@angular/core';
import { ChartOptions, ChartType, ChartDataSets } from 'chart.js';
import * as pluginDataLabels from 'chartjs-plugin-datalabels';
import { Label } from 'ng2-charts';
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
public barChartOptions: ChartOptions = {
responsive: true,
// We use these empty structures as placeholders for dynamic theming.
scales: { xAxes: [{}], yAxes: [{}] },
plugins: {
datalabels: {
anchor: 'end',
align: 'end',
font: {
size: 20,
}
}
}
};
...
public barChartPlugins = [pluginDataLabels];
...