UNPKG

15.8 kBJavaScriptView Raw
1import * as i0 from '@angular/core';
2import { InjectionToken, EventEmitter, Directive, Inject, Input, Output, NgModule } from '@angular/core';
3import { of, EMPTY, Subject, asyncScheduler, Observable } from 'rxjs';
4import { throttleTime, switchMap } from 'rxjs/operators';
5
6class ChangeFilter {
7 constructor(changes) {
8 this.changes = changes;
9 }
10 static of(changes) {
11 return new ChangeFilter(changes);
12 }
13 notEmpty(key) {
14 if (this.changes[key]) {
15 const value = this.changes[key].currentValue;
16 if (value !== undefined && value !== null) {
17 return of(value);
18 }
19 }
20 return EMPTY;
21 }
22 has(key) {
23 if (this.changes[key]) {
24 const value = this.changes[key].currentValue;
25 return of(value);
26 }
27 return EMPTY;
28 }
29 notFirst(key) {
30 if (this.changes[key] && !this.changes[key].isFirstChange()) {
31 const value = this.changes[key].currentValue;
32 return of(value);
33 }
34 return EMPTY;
35 }
36 notFirstAndEmpty(key) {
37 if (this.changes[key] && !this.changes[key].isFirstChange()) {
38 const value = this.changes[key].currentValue;
39 if (value !== undefined && value !== null) {
40 return of(value);
41 }
42 }
43 return EMPTY;
44 }
45}
46
47const NGX_ECHARTS_CONFIG = new InjectionToken('NGX_ECHARTS_CONFIG');
48class NgxEchartsDirective {
49 constructor(config, el, ngZone) {
50 this.el = el;
51 this.ngZone = ngZone;
52 this.autoResize = true;
53 this.loadingType = 'default';
54 // ngx-echarts events
55 this.chartInit = new EventEmitter();
56 this.optionsError = new EventEmitter();
57 // echarts mouse events
58 this.chartClick = this.createLazyEvent('click');
59 this.chartDblClick = this.createLazyEvent('dblclick');
60 this.chartMouseDown = this.createLazyEvent('mousedown');
61 this.chartMouseMove = this.createLazyEvent('mousemove');
62 this.chartMouseUp = this.createLazyEvent('mouseup');
63 this.chartMouseOver = this.createLazyEvent('mouseover');
64 this.chartMouseOut = this.createLazyEvent('mouseout');
65 this.chartGlobalOut = this.createLazyEvent('globalout');
66 this.chartContextMenu = this.createLazyEvent('contextmenu');
67 // echarts mouse events
68 this.chartLegendSelectChanged = this.createLazyEvent('legendselectchanged');
69 this.chartLegendSelected = this.createLazyEvent('legendselected');
70 this.chartLegendUnselected = this.createLazyEvent('legendunselected');
71 this.chartLegendScroll = this.createLazyEvent('legendscroll');
72 this.chartDataZoom = this.createLazyEvent('datazoom');
73 this.chartDataRangeSelected = this.createLazyEvent('datarangeselected');
74 this.chartTimelineChanged = this.createLazyEvent('timelinechanged');
75 this.chartTimelinePlayChanged = this.createLazyEvent('timelineplaychanged');
76 this.chartRestore = this.createLazyEvent('restore');
77 this.chartDataViewChanged = this.createLazyEvent('dataviewchanged');
78 this.chartMagicTypeChanged = this.createLazyEvent('magictypechanged');
79 this.chartPieSelectChanged = this.createLazyEvent('pieselectchanged');
80 this.chartPieSelected = this.createLazyEvent('pieselected');
81 this.chartPieUnselected = this.createLazyEvent('pieunselected');
82 this.chartMapSelectChanged = this.createLazyEvent('mapselectchanged');
83 this.chartMapSelected = this.createLazyEvent('mapselected');
84 this.chartMapUnselected = this.createLazyEvent('mapunselected');
85 this.chartAxisAreaSelected = this.createLazyEvent('axisareaselected');
86 this.chartFocusNodeAdjacency = this.createLazyEvent('focusnodeadjacency');
87 this.chartUnfocusNodeAdjacency = this.createLazyEvent('unfocusnodeadjacency');
88 this.chartBrush = this.createLazyEvent('brush');
89 this.chartBrushEnd = this.createLazyEvent('brushend');
90 this.chartBrushSelected = this.createLazyEvent('brushselected');
91 this.chartRendered = this.createLazyEvent('rendered');
92 this.chartFinished = this.createLazyEvent('finished');
93 this.animationFrameID = null;
94 this.resize$ = new Subject();
95 this.echarts = config.echarts;
96 }
97 ngOnChanges(changes) {
98 const filter = ChangeFilter.of(changes);
99 filter.notFirstAndEmpty('options').subscribe((opt) => this.onOptionsChange(opt));
100 filter.notFirstAndEmpty('merge').subscribe((opt) => this.setOption(opt));
101 filter.has('loading').subscribe((v) => this.toggleLoading(!!v));
102 filter.notFirst('theme').subscribe(() => this.refreshChart());
103 }
104 ngOnInit() {
105 if (!window.ResizeObserver) {
106 throw new Error('please install a polyfill for ResizeObserver');
107 }
108 this.resizeSub = this.resize$.pipe(throttleTime(100, asyncScheduler, { leading: false, trailing: true })).subscribe(() => this.resize());
109 if (this.autoResize) {
110 this.resizeOb = this.ngZone.runOutsideAngular(() => new window.ResizeObserver(() => {
111 this.animationFrameID = window.requestAnimationFrame(() => this.resize$.next());
112 }));
113 this.resizeOb.observe(this.el.nativeElement);
114 }
115 }
116 ngOnDestroy() {
117 window.clearTimeout(this.initChartTimer);
118 if (this.resizeSub) {
119 this.resizeSub.unsubscribe();
120 }
121 if (this.animationFrameID) {
122 window.cancelAnimationFrame(this.animationFrameID);
123 }
124 if (this.resizeOb) {
125 this.resizeOb.unobserve(this.el.nativeElement);
126 }
127 this.dispose();
128 }
129 ngAfterViewInit() {
130 this.initChartTimer = window.setTimeout(() => this.initChart());
131 }
132 dispose() {
133 if (this.chart) {
134 if (!this.chart.isDisposed()) {
135 this.chart.dispose();
136 }
137 this.chart = null;
138 }
139 }
140 /**
141 * resize chart
142 */
143 resize() {
144 if (this.chart) {
145 this.chart.resize();
146 }
147 }
148 toggleLoading(loading) {
149 if (this.chart) {
150 loading
151 ? this.chart.showLoading(this.loadingType, this.loadingOpts)
152 : this.chart.hideLoading();
153 }
154 }
155 setOption(option, opts) {
156 if (this.chart) {
157 try {
158 this.chart.setOption(option, opts);
159 }
160 catch (e) {
161 console.error(e);
162 this.optionsError.emit(e);
163 }
164 }
165 }
166 /**
167 * dispose old chart and create a new one.
168 */
169 async refreshChart() {
170 this.dispose();
171 await this.initChart();
172 }
173 createChart() {
174 const dom = this.el.nativeElement;
175 if (window && window.getComputedStyle) {
176 const prop = window.getComputedStyle(dom, null).getPropertyValue('height');
177 if ((!prop || prop === '0px') && (!dom.style.height || dom.style.height === '0px')) {
178 dom.style.height = '400px';
179 }
180 }
181 // here a bit tricky: we check if the echarts module is provided as function returning native import('...') then use the promise
182 // otherwise create the function that imitates behaviour above with a provided as is module
183 return this.ngZone.runOutsideAngular(() => {
184 const load = typeof this.echarts === 'function' ? this.echarts : () => Promise.resolve(this.echarts);
185 return load().then(({ init }) => init(dom, this.theme, this.initOpts));
186 });
187 }
188 async initChart() {
189 await this.onOptionsChange(this.options);
190 if (this.merge && this.chart) {
191 this.setOption(this.merge);
192 }
193 }
194 async onOptionsChange(opt) {
195 if (!opt) {
196 return;
197 }
198 if (this.chart) {
199 this.setOption(this.options, true);
200 }
201 else {
202 this.chart = await this.createChart();
203 this.chartInit.emit(this.chart);
204 this.setOption(this.options, true);
205 }
206 }
207 // allows to lazily bind to only those events that are requested through the `@Output` by parent components
208 // see https://stackoverflow.com/questions/51787972/optimal-reentering-the-ngzone-from-eventemitter-event for more info
209 createLazyEvent(eventName) {
210 return this.chartInit.pipe(switchMap((chart) => new Observable((observer) => {
211 chart.on(eventName, (data) => this.ngZone.run(() => observer.next(data)));
212 return () => {
213 if (this.chart) {
214 if (!this.chart.isDisposed()) {
215 chart.off(eventName);
216 }
217 }
218 };
219 })));
220 }
221}
222NgxEchartsDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.2", ngImport: i0, type: NgxEchartsDirective, deps: [{ token: NGX_ECHARTS_CONFIG }, { token: i0.ElementRef }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Directive });
223NgxEchartsDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "14.0.2", type: NgxEchartsDirective, selector: "echarts, [echarts]", inputs: { options: "options", theme: "theme", loading: "loading", initOpts: "initOpts", merge: "merge", autoResize: "autoResize", loadingType: "loadingType", loadingOpts: "loadingOpts" }, outputs: { chartInit: "chartInit", optionsError: "optionsError", chartClick: "chartClick", chartDblClick: "chartDblClick", chartMouseDown: "chartMouseDown", chartMouseMove: "chartMouseMove", chartMouseUp: "chartMouseUp", chartMouseOver: "chartMouseOver", chartMouseOut: "chartMouseOut", chartGlobalOut: "chartGlobalOut", chartContextMenu: "chartContextMenu", chartLegendSelectChanged: "chartLegendSelectChanged", chartLegendSelected: "chartLegendSelected", chartLegendUnselected: "chartLegendUnselected", chartLegendScroll: "chartLegendScroll", chartDataZoom: "chartDataZoom", chartDataRangeSelected: "chartDataRangeSelected", chartTimelineChanged: "chartTimelineChanged", chartTimelinePlayChanged: "chartTimelinePlayChanged", chartRestore: "chartRestore", chartDataViewChanged: "chartDataViewChanged", chartMagicTypeChanged: "chartMagicTypeChanged", chartPieSelectChanged: "chartPieSelectChanged", chartPieSelected: "chartPieSelected", chartPieUnselected: "chartPieUnselected", chartMapSelectChanged: "chartMapSelectChanged", chartMapSelected: "chartMapSelected", chartMapUnselected: "chartMapUnselected", chartAxisAreaSelected: "chartAxisAreaSelected", chartFocusNodeAdjacency: "chartFocusNodeAdjacency", chartUnfocusNodeAdjacency: "chartUnfocusNodeAdjacency", chartBrush: "chartBrush", chartBrushEnd: "chartBrushEnd", chartBrushSelected: "chartBrushSelected", chartRendered: "chartRendered", chartFinished: "chartFinished" }, exportAs: ["echarts"], usesOnChanges: true, ngImport: i0 });
224i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.2", ngImport: i0, type: NgxEchartsDirective, decorators: [{
225 type: Directive,
226 args: [{
227 selector: 'echarts, [echarts]',
228 exportAs: 'echarts',
229 }]
230 }], ctorParameters: function () { return [{ type: undefined, decorators: [{
231 type: Inject,
232 args: [NGX_ECHARTS_CONFIG]
233 }] }, { type: i0.ElementRef }, { type: i0.NgZone }]; }, propDecorators: { options: [{
234 type: Input
235 }], theme: [{
236 type: Input
237 }], loading: [{
238 type: Input
239 }], initOpts: [{
240 type: Input
241 }], merge: [{
242 type: Input
243 }], autoResize: [{
244 type: Input
245 }], loadingType: [{
246 type: Input
247 }], loadingOpts: [{
248 type: Input
249 }], chartInit: [{
250 type: Output
251 }], optionsError: [{
252 type: Output
253 }], chartClick: [{
254 type: Output
255 }], chartDblClick: [{
256 type: Output
257 }], chartMouseDown: [{
258 type: Output
259 }], chartMouseMove: [{
260 type: Output
261 }], chartMouseUp: [{
262 type: Output
263 }], chartMouseOver: [{
264 type: Output
265 }], chartMouseOut: [{
266 type: Output
267 }], chartGlobalOut: [{
268 type: Output
269 }], chartContextMenu: [{
270 type: Output
271 }], chartLegendSelectChanged: [{
272 type: Output
273 }], chartLegendSelected: [{
274 type: Output
275 }], chartLegendUnselected: [{
276 type: Output
277 }], chartLegendScroll: [{
278 type: Output
279 }], chartDataZoom: [{
280 type: Output
281 }], chartDataRangeSelected: [{
282 type: Output
283 }], chartTimelineChanged: [{
284 type: Output
285 }], chartTimelinePlayChanged: [{
286 type: Output
287 }], chartRestore: [{
288 type: Output
289 }], chartDataViewChanged: [{
290 type: Output
291 }], chartMagicTypeChanged: [{
292 type: Output
293 }], chartPieSelectChanged: [{
294 type: Output
295 }], chartPieSelected: [{
296 type: Output
297 }], chartPieUnselected: [{
298 type: Output
299 }], chartMapSelectChanged: [{
300 type: Output
301 }], chartMapSelected: [{
302 type: Output
303 }], chartMapUnselected: [{
304 type: Output
305 }], chartAxisAreaSelected: [{
306 type: Output
307 }], chartFocusNodeAdjacency: [{
308 type: Output
309 }], chartUnfocusNodeAdjacency: [{
310 type: Output
311 }], chartBrush: [{
312 type: Output
313 }], chartBrushEnd: [{
314 type: Output
315 }], chartBrushSelected: [{
316 type: Output
317 }], chartRendered: [{
318 type: Output
319 }], chartFinished: [{
320 type: Output
321 }] } });
322
323class NgxEchartsModule {
324 static forRoot(config) {
325 return {
326 ngModule: NgxEchartsModule,
327 providers: [{ provide: NGX_ECHARTS_CONFIG, useValue: config }],
328 };
329 }
330 static forChild() {
331 return {
332 ngModule: NgxEchartsModule,
333 };
334 }
335}
336NgxEchartsModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.2", ngImport: i0, type: NgxEchartsModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
337NgxEchartsModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "14.0.2", ngImport: i0, type: NgxEchartsModule, declarations: [NgxEchartsDirective], exports: [NgxEchartsDirective] });
338NgxEchartsModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "14.0.2", ngImport: i0, type: NgxEchartsModule });
339i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.2", ngImport: i0, type: NgxEchartsModule, decorators: [{
340 type: NgModule,
341 args: [{
342 imports: [],
343 declarations: [NgxEchartsDirective],
344 exports: [NgxEchartsDirective],
345 }]
346 }] });
347
348/*
349 * Public API Surface of ngx-echarts
350 */
351
352/**
353 * Generated bundle index. Do not edit.
354 */
355
356export { NGX_ECHARTS_CONFIG, NgxEchartsDirective, NgxEchartsModule };
357//# sourceMappingURL=ngx-echarts.mjs.map