@rdkmaster/jigsaw-labs
Version:
Jigsaw, the next generation component set for RDK
359 lines (298 loc) • 10.7 kB
text/typescript
/**
* Created by 10177553 on 2017/3/23.
*/
import {AfterViewInit, Component, ElementRef, EventEmitter, Input, NgZone, OnDestroy, OnInit, Output, Renderer2,} from "@angular/core";
import {AbstractGraphData} from "../../core/data/graph-data";
import {CallbackRemoval, CommonUtils} from "../../core/utils/common-utils";
import {AbstractJigsawComponent} from "../common";
import {EchartOptions} from "../../core/data/echart-types";
import {VMAX_GRAPH_THEME} from "./vmax-theme";
import {VMAX_GRAPH_THEME_DARK} from './vmax-theme-dark';
import {JigsawTheme} from "../../core/theming/theme";
export class JigsawGraph extends AbstractJigsawComponent implements OnInit, OnDestroy, AfterViewInit {
// TODO 当前属性判断不正确, 当前判断是是否option为空
public dataValid: boolean = false;
// 通过 echarts.init 创建的实例
private _graph: any;
/**
* @internal
*/
public _$noDataSrc = CommonUtils.noDataImageSrc;
// 由数据服务提供的数据.
private _data: AbstractGraphData;
public get data(): AbstractGraphData {
return this._data;
}
private _removeRefreshCallback: CallbackRemoval;
public set data(value: AbstractGraphData) {
if (!value) return;
this._data = value;
const opt = value.options;
this.setOption(opt);
if (this._removeRefreshCallback) {
this._removeRefreshCallback();
}
this._removeRefreshCallback = value.onRefresh(() => {
this.setOption(value.options);
});
}
public get width(): string {
return this._width;
}
public set width(value: string) {
this._width = CommonUtils.getCssValue(value);
this._renderer.setStyle(this._host, 'width', this._width);
if (this.initialized) {
this.resize();
this._listenWindowResize();
}
}
public get height(): string {
return this._height;
}
public set height(value: string) {
this._height = CommonUtils.getCssValue(value);
this._renderer.setStyle(this._host, 'height', this._height);
if (this.initialized) {
this.resize();
this._listenWindowResize();
}
}
private _globalTheme: any = JigsawTheme.majorStyle == 'dark' ? VMAX_GRAPH_THEME_DARK : VMAX_GRAPH_THEME;
public get globalTheme() {
return this._globalTheme;
};
public set globalTheme(value) {
if (!value) return;
this._globalTheme = value;
if (this._graph) {
this._graph._theme = value;
this.data.refresh();
}
}
constructor(private _elementRef: ElementRef, private _renderer: Renderer2, private _zone: NgZone) {
super();
this._host = this._elementRef.nativeElement;
}
/**
* 判断对象是否为空
* @param obj
*/
private _isOptionsValid(obj): boolean {
return !CommonUtils.isEmptyObject(obj);
}
public setOption(option: EchartOptions, lazyUpdate?: boolean) {
if (!this._graph) {
return;
}
this.dataValid = this._isOptionsValid(this.data.options);
// 若数据非法,那么不能给graph赋值,故直接返回
if (!this.dataValid) {
return;
}
this._graph.setOption(option, true, lazyUpdate);
this._registerEvent();
}
public resize(): void {
if (this._graph) {
this._graph.resize({
width: this._host.offsetWidth + 'px',
height: this._host.offsetHeight + 'px',
silence: true
});
}
}
private _resizeEventRemoval: Function;
private _listenWindowResize(): void {
if (!this._needListenWindowResize() || this._resizeEventRemoval) {
return;
}
this._zone.runOutsideAngular(() => {
// 所有的全局事件应该放到zone外面,不一致会导致removeEvent失效,见#286
this._resizeEventRemoval = this._renderer.listen("window", "resize", () => {
this.resize();
});
});
}
private _needListenWindowResize(): boolean {
return !!((this.width && this.width[this.width.length - 1] == '%') ||
(this.height && this.height[this.height.length - 1] == '%') || !this.width);
}
private _host: HTMLElement;
private _graphContainer: HTMLElement;
ngOnInit() {
super.ngOnInit();
if (this.data) {
this.dataValid = this._isOptionsValid(this.data.options);
}
this.init.emit();
}
ngAfterViewInit() {
this._renderer.addClass(this._host, 'jigsaw-graph-host');
this._graphContainer = <HTMLElement>this._host.querySelector(".jigsaw-graph");
this._zone.runOutsideAngular(() => {
// echarts的Animation对象里的_startLoop方法有个递归调用requestAnimationFrame,会触发变更检查,见#289
this._graph = echarts.init(this._graphContainer);
this._graph._theme = this.globalTheme;
});
this._listenWindowResize();
if (this.data) {
this.setOption(this.data.options);
}
}
ngOnDestroy() {
if (this._resizeEventRemoval) {
this._resizeEventRemoval();
this._resizeEventRemoval = null;
}
if (this._graph) {
this._graph.dispose();
this._graph = null;
}
}
// 注册封装的echarts事件.
private _registerEvent() {
this._eventArr.forEach(eventStr => {
this._graph.off(eventStr);
this._graph.on(eventStr, params => this._handleEvent(params, eventStr));
})
}
private _handleEvent(params: any, eventType?: string) {
// 防止和ng2 事件冲突,响应两遍.
if (!!event) {
event.preventDefault();
event.stopPropagation();
}
this._zone.run(() => {
this[eventType].emit(params)
});
}
/* ********************** echarts api 封装区 start ******************************** */
public registerMap(mapName: string, geoJson: Object, specialAreas?: Object): void {
echarts.registerMap(mapName, geoJson, specialAreas);
}
public getMapMap(mapName: string): Object {
return echarts.getMap(mapName);
}
public registerTheme(themeName: string, theme: Object): void {
echarts.registerTheme(themeName, theme);
}
public dispatchAction(payload: Object): void {
this._graph.dispatchAction(payload);
}
public on(eventName: string, handler: Function, context?: Object): void {
this._graph.on(eventName, handler, context);
}
public off(eventName: string, handler?: Function): void {
this._graph.off(eventName, handler);
}
public showLoading(type?: string, opts?: Object): void {
this._graph.showLoading(type, opts);
}
public hideLoading(): void {
this._graph.hideLoading();
}
public clear(): void {
this._graph.clear();
}
public isDisposed(): boolean {
return this._graph.isDisposed();
}
public dispose(): void {
this._graph.dispose();
}
/* ********************** echarts api 封装区 end ******************************** */
/* *************** 事件声明 start ***************************** */
// 1. 像饼图的事件等放到对应的组件中
private _eventArr = ['click', 'dblclick', 'mousedown', 'mouseup', 'mouseover', 'mouseout',
'globalout', 'contextmenu', 'legendselectchanged', 'legendselected', 'legendunselected',
'datazoom', 'datarangeselected', 'timelinechanged', 'timelineplaychanged', 'restore',
'dataviewchanged', 'magictypechanged', 'geoselectchanged', 'geoselected', 'geounselected',
'pieselectchanged', 'pieselected', 'pieunselected', 'mapselectchanged', 'mapselected',
'brush', 'brushselected'];
// **************** 鼠标事件 start
public click = new EventEmitter<any>();
public dblclick = new EventEmitter<any>();
public mousedown = new EventEmitter<any>();
public mouseup = new EventEmitter<any>();
public mouseover = new EventEmitter<any>();
public mouseout = new EventEmitter<any>();
public globalout = new EventEmitter<any>();
public contextmenu = new EventEmitter<any>();
// **************** 鼠标事件 end
public legendselectchanged = new EventEmitter<any>();
public legendselected = new EventEmitter<any>();
public legendunselected = new EventEmitter<any>();
public datazoom = new EventEmitter<any>();
public datarangeselected = new EventEmitter<any>();
public timelinechanged = new EventEmitter<any>();
public timelineplaychanged = new EventEmitter<any>();
public restore = new EventEmitter<any>();
// 工具栏
public dataviewchanged = new EventEmitter<any>();
public magictypechanged = new EventEmitter<any>();
// 地图
public geoselectchanged = new EventEmitter<any>();
public geoselected = new EventEmitter<any>();
public geounselected = new EventEmitter<any>();
// 饼图
public pieselectchanged = new EventEmitter<any>();
public pieselected = new EventEmitter<any>();
public pieunselected = new EventEmitter<any>();
// 地图:
public mapselectchanged = new EventEmitter<any>();
public mapselected = new EventEmitter<any>();
public mapunselected = new EventEmitter<any>();
// 平行坐标轴
public axisareaselected = new EventEmitter<any>();
// basic
public focusNodeAdjacency = new EventEmitter<any>();
public unfocusNodeAdjacency = new EventEmitter<any>();
// 区域选择
public brush = new EventEmitter<any>();
public brushselected = new EventEmitter<any>();
// 将onInit 暴露给外面
public init = new EventEmitter<any>();
/* *************** 事件声明 end ***************************** */
}