import { Component, Input, HostBinding, ViewChild, ElementRef, OnDestroy, OnChanges, SimpleChanges, NgZone, AfterViewInit, TemplateRef } from '@angular/core'; @Component({ selector: 'timeline', template: `

{{_title}}

` }) export class TimelineComponent implements OnDestroy, OnChanges, AfterViewInit { // region: fields _title = ''; _titleTpl: TemplateRef; @Input() set title(value: string | TemplateRef) { if (value instanceof TemplateRef) this._titleTpl = value; else this._title = value; } @Input() data: any[]; @Input() titleMap: any; @Input() height = 400; @Input() margin: number[] = [60, 20, 40, 40]; @Input() borderWidth = 2; // endregion @ViewChild('container') node: ElementRef; @ViewChild('slider') sliderNode: ElementRef; chart: any; initFlag = false; slider: any; constructor(private zone: NgZone) { } ngAfterViewInit(): void { this.initFlag = true; this.installDelay(); } installDelay() { // TODO: 很多场景可能会在组件加载后才呈现,导致无法渲染 setTimeout(() => this.install(), 100); } install() { if (!this.data || (this.data && this.data.length < 1)) return; this.uninstall(); this.zone.runOutsideAngular(() => { // clean if (this.sliderNode) { this.sliderNode.nativeElement.id = `timeline-chart-slider-${Math.random() * 1000}`; this.sliderNode.nativeElement.innerHTML = ''; } this.node.nativeElement.innerHTML = ''; const chart = new G2.Chart({ container: this.node.nativeElement, forceFit: true, height: this.height, plotCfg: { margin: this.margin } }); chart.axis('x', { title: false }); chart.axis('y1', { title: false }); chart.axis('y2', false); chart.legend({ mode: false, position: 'top' }); let max; if (this.data[0] && this.data[0].y1 && this.data[0].y2) { max = Math.max( this.data.sort((a, b) => b.y1 - a.y1)[0].y1, this.data.sort((a, b) => b.y2 - a.y2)[0].y2 ); } chart.source(this.data, { x: { type: 'timeCat', tickCount: 16, mask: 'HH:MM', range: [0, 1] }, y1: { alias: this.titleMap.y1, max, min: 0 }, y2: { alias: this.titleMap.y2, max, min: 0 } }); chart.line().position('x*y1').color('#1890FF').size(this.borderWidth); chart.line().position('x*y2').color('#2FC25B').size(this.borderWidth); const slider = new Slider({ domId: this.sliderNode.nativeElement.id, height: 26, xDim: 'x', yDim: 'y1', charts: [chart] }); slider.render(); this.zone.run(() => { this.chart = chart; this.slider = slider; }); }); } uninstall() { this.zone.runOutsideAngular(() => { if (this.chart) this.chart.destroy(); if (this.slider) this.slider.destroy(); }); } ngOnChanges(changes: SimpleChanges): void { if (this.initFlag) this.installDelay(); } ngOnDestroy(): void { this.uninstall(); } }