2018-04-16 09:52:39 +02:00

143 lines
4.5 KiB
TypeScript

// (C) Copyright 2015 Martin Dougiamas
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import { Directive, Input, OnDestroy, OnInit, ElementRef, OnChanges } from '@angular/core';
import { Chart } from 'chart.js';
/**
* This component shows a chart using chart.js.
* Documentation can be found at http://www.chartjs.org/docs/.
* It only supports changes on these properties: data and labels.
*
* Example usage:
* <canvas core-chart [data]="data" [labels]="labels" [type]="type" [legend]="legend"></canvas>
*/
@Directive({
selector: 'canvas[core-chart]'
})
export class CoreChartDirective implements OnDestroy, OnInit, OnChanges {
// The first 6 colors will be the app colors, the following will be randomly generated.
// It will use the same colors in the whole session.
protected static backgroundColors = [
'rgba(0,100,210, 0.6)',
'rgba(203,61,77, 0.6)',
'rgba(0,121,130, 0.6)',
'rgba(249,128,18, 0.6)',
'rgba(94,129,0, 0.6)',
'rgba(251,173,26, 0.6)'
];
@Input() data: any[]; // Chart data.
@Input() labels = []; // Labels of the data.
@Input() type: string; // Type of chart.
@Input() legend: any; // Legend options.
chart: any;
protected element: ElementRef;
constructor(element: ElementRef) {
this.element = element;
}
/**
* Component being initialized.
*/
ngOnInit(): any {
let legend = {};
if (typeof this.legend == 'undefined') {
legend = {
display: true,
position: 'bottom',
labels: {
generateLabels: (chart): any => {
const data = chart.data;
if (data.labels.length && data.labels.length) {
const datasets = data.datasets[0];
return data.labels.map((label, i): any => {
return {
text: label + ': ' + datasets.data[i],
fillStyle: datasets.backgroundColor[i]
};
});
}
return [];
}
}
};
} else {
legend = Object.assign({}, this.legend);
}
if (this.type == 'bar' && this.data.length >= 5) {
this.type = 'horizontalBar';
}
const context = this.element.nativeElement.getContext('2d');
this.chart = new Chart(context, {
type: this.type,
data: {
labels: this.labels,
datasets: [{
data: this.data,
backgroundColor: this.getRandomColors(this.data.length)
}]
},
options: {legend: legend}
});
}
/**
* Listen to chart changes.
*/
ngOnChanges(): void {
if (this.chart) {
this.chart.data.datasets[0] = {
data: this.data,
backgroundColor: this.getRandomColors(this.data.length)
};
this.chart.data.labels = this.labels;
this.chart.update();
}
}
/**
* Generate random colors if needed.
*
* @param {number} n Number of colors needed.
* @return {any[]} Array with the number of background colors requested.
*/
protected getRandomColors(n: number): any[] {
while (CoreChartDirective.backgroundColors.length < n) {
const red = Math.floor(Math.random() * 255),
green = Math.floor(Math.random() * 255),
blue = Math.floor(Math.random() * 255);
CoreChartDirective.backgroundColors.push('rgba(' + red + ', ' + green + ', ' + blue + ', 0.6)');
}
return CoreChartDirective.backgroundColors.slice(0, n);
}
/**
* Component being destroyed.
*/
ngOnDestroy(): any {
if (this.chart) {
this.chart.destroy();
this.chart = false;
}
}
}