import { AfterViewInit, ChangeDetectionStrategy, Component, DoCheck, ElementRef, Input, OnInit, ViewChild } from '@angular/core'; import { TranslateService } from "@ngx-translate/core"; import { forkJoin } from "rxjs"; @Component({ selector: 'histogram-chart', templateUrl: './histogram-chart.component.html', styleUrls: ['./histogram-chart.component.scss'], changeDetection: ChangeDetectionStrategy.OnPush }) export class HistogramChartComponent implements OnInit, AfterViewInit, DoCheck { @Input() metadata: Array<{ text: string, value: number, color: string }> = []; translatedTextArr: Array = []; @Input() isWhiteBackground: boolean = false; max: number; scale: number; hasViewInit: boolean = false; @ViewChild('barChart') barChart: ElementRef; public context: CanvasRenderingContext2D; constructor(private translate: TranslateService) { } ngOnInit() { this.translateText(); } ngAfterViewInit(): void { this.hasViewInit = true; this.initChart(); } ngDoCheck() { if (this.hasViewInit) { this.initChart(); } } translateText() { if (this.metadata && this.metadata.length > 0) { let textArr = []; this.metadata.forEach(item => { textArr.push(this.translate.get(item.text)); }); forkJoin(textArr).subscribe( (res: string[]) => { this.translatedTextArr = res; if (this.hasViewInit) { this.initChart(); } } ); } } initChart() { if (this.barChart && this.metadata && this.metadata.length > 0) { this.barChart.nativeElement.width = "240"; this.barChart.nativeElement.height = 25 + 20 * this.metadata.length + ""; this.context = this.barChart.nativeElement.getContext('2d'); this.getMax(); if (this.isWhiteBackground) { this.context.fillStyle = "#000"; } else { this.context.fillStyle = "#fff"; } this.drawLine(50, 0, 50, 5 + this.metadata.length * 20); this.drawLine(50, 5 + this.metadata.length * 20, 250, 5 + this.metadata.length * 20); this.drawLine(90, 5 + this.metadata.length * 20, 90, 2 + this.metadata.length * 20); this.drawLine(130, 5 + this.metadata.length * 20, 130, 2 + this.metadata.length * 20); this.drawLine(170, 5 + this.metadata.length * 20, 170, 2 + this.metadata.length * 20); this.drawLine(210, 5 + this.metadata.length * 20, 210, 2 + this.metadata.length * 20); this.context.font = "12px"; this.context.textAlign = "center"; this.context.fillText(this.scale.toString(), 90, this.metadata.length * 20 + 18, 50); this.context.fillText((2 * this.scale).toString(), 130, this.metadata.length * 20 + 18, 50); this.context.fillText((3 * this.scale).toString(), 170, this.metadata.length * 20 + 18, 50); this.context.fillText((4 * this.scale).toString(), 210, this.metadata.length * 20 + 18, 50); this.metadata.forEach((item, index) => { this.drawBar(index, item.color, item.value); }); } } drawBar(index: number, color: string, value: number) { this.context.textBaseline = "middle"; this.context.textAlign = "left"; this.context.fillStyle = color; this.context.fillRect(50, 5 + index * 20, value / this.scale * 40, 15); this.context.fillText(value.toString(), (value / this.scale * 40) + 53, 12 + index * 20, 37); this.context.textAlign = "right"; let text = ""; if (this.translatedTextArr && this.translatedTextArr.length > 0) { text = this.translatedTextArr[index]; } else { text = this.metadata[index].text; } this.context.fillText(text, 47, 12 + index * 20, 47); } drawLine(x, y, X, Y) { this.context.beginPath(); this.context.moveTo(x, y); this.context.lineTo(X, Y); if (this.isWhiteBackground) { this.context.strokeStyle = "#000"; } else { this.context.strokeStyle = "#fff"; } this.context.stroke(); this.context.closePath(); } getMax() { let count = 1; if (this.metadata && this.metadata.length > 0) { this.metadata.forEach(item => { if (item.value > count) { count = item.value; } }); } this.max = count; this.scale = Math.ceil(count / 40) * 10; } }