@visionaris-bruno/vs-echarts 5.9.2 → 6.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -11
- package/fesm2022/visionaris-bruno-vs-echarts.mjs +1111 -929
- package/fesm2022/visionaris-bruno-vs-echarts.mjs.map +1 -1
- package/index.d.ts +297 -152
- package/package.json +1 -1
|
@@ -3,33 +3,14 @@ import * as echarts from 'echarts/core';
|
|
|
3
3
|
import { BarChart, PieChart, LineChart } from 'echarts/charts';
|
|
4
4
|
import { TitleComponent, TooltipComponent, GridComponent, LegendComponent, GraphicComponent, ToolboxComponent, PolarComponent } from 'echarts/components';
|
|
5
5
|
import { CanvasRenderer } from 'echarts/renderers';
|
|
6
|
-
import merge from 'lodash/merge';
|
|
7
6
|
import * as i0 from '@angular/core';
|
|
8
7
|
import { EventEmitter, Output, Input, ViewChild, Directive, Component } from '@angular/core';
|
|
9
8
|
import { ReplaySubject } from 'rxjs';
|
|
10
9
|
import { debounceTime } from 'rxjs/operators';
|
|
10
|
+
import merge from 'lodash/merge';
|
|
11
11
|
import { CommonModule } from '@angular/common';
|
|
12
|
+
import { merge as merge$1 } from 'lodash';
|
|
12
13
|
|
|
13
|
-
/**
|
|
14
|
-
* ECharts Options Standard Library
|
|
15
|
-
*
|
|
16
|
-
* Biblioteca de fragmentos de configuración y tokens de diseño para asegurar
|
|
17
|
-
* una estética cohesiva en todos los gráficos de Visionaris.
|
|
18
|
-
*
|
|
19
|
-
* @see {@link VisionarisFrontEnd/docs/technical/echarts-architecture.md}
|
|
20
|
-
*/
|
|
21
|
-
// Pre-cached native formatter for performance in axis ticks
|
|
22
|
-
const compactFormatter = new Intl.NumberFormat('es-AR', {
|
|
23
|
-
notation: 'compact',
|
|
24
|
-
compactDisplay: 'short',
|
|
25
|
-
maximumFractionDigits: 1
|
|
26
|
-
});
|
|
27
|
-
/**
|
|
28
|
-
* Formats a value using native browser SI suffixes (k, M, B).
|
|
29
|
-
*/
|
|
30
|
-
function formatAxisValue(value) {
|
|
31
|
-
return compactFormatter.format(value);
|
|
32
|
-
}
|
|
33
14
|
/**
|
|
34
15
|
* Global Design Tokens for ECharts
|
|
35
16
|
*/
|
|
@@ -48,265 +29,6 @@ const EChartsTokens = {
|
|
|
48
29
|
function getDefaultPalette() {
|
|
49
30
|
return [...EChartsTokens.defaultPalette];
|
|
50
31
|
}
|
|
51
|
-
/**
|
|
52
|
-
* Common legend configuration with scroll to prevent "cannibalization".
|
|
53
|
-
* Atomic Pattern: Provides the scrollable container with Visionaris styling.
|
|
54
|
-
*/
|
|
55
|
-
function getLegendOptions(overrides) {
|
|
56
|
-
const defaults = {
|
|
57
|
-
show: true,
|
|
58
|
-
type: 'scroll',
|
|
59
|
-
orient: 'horizontal',
|
|
60
|
-
bottom: 0,
|
|
61
|
-
left: 'center',
|
|
62
|
-
height: 60,
|
|
63
|
-
textStyle: {
|
|
64
|
-
color: '#333',
|
|
65
|
-
fontSize: EChartsTokens.fontSize,
|
|
66
|
-
fontFamily: EChartsTokens.fontFamily
|
|
67
|
-
},
|
|
68
|
-
pageButtonPosition: 'end',
|
|
69
|
-
pageIconColor: EChartsTokens.primaryColor,
|
|
70
|
-
pageIconInactiveColor: '#ccc',
|
|
71
|
-
pageIconSize: 12,
|
|
72
|
-
pageTextStyle: {
|
|
73
|
-
color: '#666'
|
|
74
|
-
}
|
|
75
|
-
};
|
|
76
|
-
return merge({}, defaults, overrides);
|
|
77
|
-
}
|
|
78
|
-
function getCategoryAxisOptions(overrides) {
|
|
79
|
-
const categories = overrides?.data ?? [];
|
|
80
|
-
const autoRotate = categories.length > 10 ? 45 : 0;
|
|
81
|
-
const defaults = {
|
|
82
|
-
type: 'category',
|
|
83
|
-
triggerEvent: true,
|
|
84
|
-
data: categories,
|
|
85
|
-
axisLabel: {
|
|
86
|
-
rotate: autoRotate,
|
|
87
|
-
interval: 0,
|
|
88
|
-
fontFamily: EChartsTokens.fontFamily,
|
|
89
|
-
color: EChartsTokens.axisColor,
|
|
90
|
-
fontSize: EChartsTokens.fontSize,
|
|
91
|
-
margin: 8,
|
|
92
|
-
fontWeight: 'normal',
|
|
93
|
-
overflow: 'break',
|
|
94
|
-
width: 1000,
|
|
95
|
-
},
|
|
96
|
-
axisLine: {
|
|
97
|
-
lineStyle: {
|
|
98
|
-
color: EChartsTokens.lineColor
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
};
|
|
102
|
-
return merge({}, defaults, overrides);
|
|
103
|
-
}
|
|
104
|
-
function getValueAxisOptions(overrides) {
|
|
105
|
-
const defaults = {
|
|
106
|
-
type: 'value',
|
|
107
|
-
splitLine: {
|
|
108
|
-
show: true,
|
|
109
|
-
lineStyle: {
|
|
110
|
-
type: 'dashed',
|
|
111
|
-
color: '#f0f0f0'
|
|
112
|
-
}
|
|
113
|
-
},
|
|
114
|
-
axisLabel: {
|
|
115
|
-
formatter: (value) => formatAxisValue(value),
|
|
116
|
-
color: EChartsTokens.axisColor,
|
|
117
|
-
fontSize: EChartsTokens.fontSize
|
|
118
|
-
}
|
|
119
|
-
};
|
|
120
|
-
return merge({}, defaults, overrides);
|
|
121
|
-
}
|
|
122
|
-
/**
|
|
123
|
-
* Callback function to dynamically position the tooltip inside the chart container boundaries.
|
|
124
|
-
*/
|
|
125
|
-
function getTooltipPositionCallback(point, params, dom, rect, size) {
|
|
126
|
-
const [x, y] = point;
|
|
127
|
-
const tooltipWidth = size?.contentSize?.[0] || dom?.offsetWidth || 150;
|
|
128
|
-
const tooltipHeight = size?.contentSize?.[1] || dom?.offsetHeight || 100;
|
|
129
|
-
const containerWidth = size?.viewSize?.[0] || 400;
|
|
130
|
-
const containerHeight = size?.viewSize?.[1] || 300;
|
|
131
|
-
const offset = 15; // Safe distance from cursor
|
|
132
|
-
let posX = x - tooltipWidth / 2;
|
|
133
|
-
let posY = y - tooltipHeight - offset; // default: above the cursor
|
|
134
|
-
// Left and right boundary checks
|
|
135
|
-
if (posX < 0) {
|
|
136
|
-
// Overflows left boundary: place to the right of the cursor
|
|
137
|
-
posX = x + offset;
|
|
138
|
-
}
|
|
139
|
-
else if (posX + tooltipWidth > containerWidth) {
|
|
140
|
-
// Overflows right boundary: place to the left of the cursor
|
|
141
|
-
posX = x - tooltipWidth - offset;
|
|
142
|
-
}
|
|
143
|
-
// Final safety clamp to container boundaries
|
|
144
|
-
if (posX + tooltipWidth > containerWidth) {
|
|
145
|
-
posX = Math.max(0, containerWidth - tooltipWidth);
|
|
146
|
-
}
|
|
147
|
-
if (posX < 0) {
|
|
148
|
-
posX = 0;
|
|
149
|
-
}
|
|
150
|
-
// Top and bottom boundary checks
|
|
151
|
-
if (posY < 0) {
|
|
152
|
-
// Overflows top boundary: place below the cursor
|
|
153
|
-
posY = y + offset;
|
|
154
|
-
}
|
|
155
|
-
else if (posY + tooltipHeight > containerHeight) {
|
|
156
|
-
// Overflows bottom boundary: place above the cursor
|
|
157
|
-
posY = y - tooltipHeight - offset;
|
|
158
|
-
}
|
|
159
|
-
// Final safety clamp to container boundaries
|
|
160
|
-
if (posY + tooltipHeight > containerHeight) {
|
|
161
|
-
posY = Math.max(0, containerHeight - tooltipHeight);
|
|
162
|
-
}
|
|
163
|
-
if (posY < 0) {
|
|
164
|
-
posY = 0;
|
|
165
|
-
}
|
|
166
|
-
return [posX, posY];
|
|
167
|
-
}
|
|
168
|
-
/**
|
|
169
|
-
* Common Tooltip configuration.
|
|
170
|
-
* Atomic Pattern: Enforces consistent glassmorphism and pointer styles.
|
|
171
|
-
*/
|
|
172
|
-
function getTooltipOptions(overrides) {
|
|
173
|
-
const trigger = overrides?.trigger || 'axis';
|
|
174
|
-
const isAxis = trigger === 'axis';
|
|
175
|
-
const defaults = {
|
|
176
|
-
show: true,
|
|
177
|
-
trigger: trigger,
|
|
178
|
-
position: getTooltipPositionCallback,
|
|
179
|
-
backgroundColor: EChartsTokens.tooltipBg,
|
|
180
|
-
borderColor: '#eee',
|
|
181
|
-
borderWidth: 1,
|
|
182
|
-
textStyle: {
|
|
183
|
-
color: '#333',
|
|
184
|
-
fontSize: 12
|
|
185
|
-
},
|
|
186
|
-
extraCssText: 'box-shadow: 0 0 10px rgba(0,0,0,0.1); border-radius: 8px;',
|
|
187
|
-
...(isAxis ? {
|
|
188
|
-
axisPointer: {
|
|
189
|
-
type: 'shadow'
|
|
190
|
-
}
|
|
191
|
-
} : {})
|
|
192
|
-
};
|
|
193
|
-
return merge({}, defaults, overrides);
|
|
194
|
-
}
|
|
195
|
-
/**
|
|
196
|
-
* Applies a visual selection effect to line-based series.
|
|
197
|
-
* Highlights the selected series and point, and dims everything else.
|
|
198
|
-
*
|
|
199
|
-
* @param series The series array to modify
|
|
200
|
-
* @param selectedCategoryIndex Index of the selected category
|
|
201
|
-
* @param selectedSeriesIndex Index of the selected series
|
|
202
|
-
* @returns Modified series array
|
|
203
|
-
*/
|
|
204
|
-
function applyLineSelectionStyle(series, selectedCategoryIndex, selectedSeriesIndex) {
|
|
205
|
-
if (selectedCategoryIndex === null || !series)
|
|
206
|
-
return series;
|
|
207
|
-
return series.map((s, sIdx) => {
|
|
208
|
-
const isSelectedSeries = sIdx === selectedSeriesIndex;
|
|
209
|
-
// Serie seleccionada: Línea con opacidad 1 para que destaque la tendencia.
|
|
210
|
-
// Serie NO seleccionada: Opacidad 0.20 para atenuar fuertemente.
|
|
211
|
-
const seriesOpacity = isSelectedSeries ? 1 : 0.20;
|
|
212
|
-
return {
|
|
213
|
-
...s,
|
|
214
|
-
emphasis: {
|
|
215
|
-
disabled: true // Deshabilitar el énfasis (hover) cuando hay una selección activa
|
|
216
|
-
},
|
|
217
|
-
itemStyle: {
|
|
218
|
-
...s.itemStyle,
|
|
219
|
-
opacity: seriesOpacity
|
|
220
|
-
},
|
|
221
|
-
lineStyle: {
|
|
222
|
-
...s.lineStyle,
|
|
223
|
-
opacity: seriesOpacity
|
|
224
|
-
},
|
|
225
|
-
...(s.areaStyle ? {
|
|
226
|
-
areaStyle: {
|
|
227
|
-
...s.areaStyle,
|
|
228
|
-
opacity: isSelectedSeries ? 0.6 : 0.1
|
|
229
|
-
}
|
|
230
|
-
} : {}),
|
|
231
|
-
// Personalizamos los puntos individualmente
|
|
232
|
-
data: (s.data || []).map((val, idx) => {
|
|
233
|
-
const isSelectedPoint = isSelectedSeries && idx === selectedCategoryIndex;
|
|
234
|
-
const isOtherPointInSelectedSeries = isSelectedSeries && idx !== selectedCategoryIndex;
|
|
235
|
-
const originalPoint = (val && typeof val === 'object') ? val : { value: val };
|
|
236
|
-
if (isSelectedPoint) {
|
|
237
|
-
return {
|
|
238
|
-
...originalPoint,
|
|
239
|
-
z: 10, // Asegurar que el punto seleccionado esté por encima de los demás
|
|
240
|
-
itemStyle: {
|
|
241
|
-
...originalPoint.itemStyle,
|
|
242
|
-
opacity: 1,
|
|
243
|
-
borderWidth: 2,
|
|
244
|
-
borderColor: '#fff',
|
|
245
|
-
shadowBlur: 10,
|
|
246
|
-
shadowColor: 'rgba(0,0,0,0.5)'
|
|
247
|
-
},
|
|
248
|
-
symbolSize: 12
|
|
249
|
-
};
|
|
250
|
-
}
|
|
251
|
-
else if (isOtherPointInSelectedSeries) {
|
|
252
|
-
// Puntos de la serie seleccionada que NO son el clicado: un poco más pequeños y traslúcidos
|
|
253
|
-
return {
|
|
254
|
-
...originalPoint,
|
|
255
|
-
itemStyle: {
|
|
256
|
-
...originalPoint.itemStyle,
|
|
257
|
-
opacity: 0.5
|
|
258
|
-
},
|
|
259
|
-
symbolSize: 6
|
|
260
|
-
};
|
|
261
|
-
}
|
|
262
|
-
// Puntos de otras series o por defecto
|
|
263
|
-
return val;
|
|
264
|
-
})
|
|
265
|
-
};
|
|
266
|
-
});
|
|
267
|
-
}
|
|
268
|
-
/**
|
|
269
|
-
* Formatter generator for 'item' trigger strategy in tooltips.
|
|
270
|
-
*/
|
|
271
|
-
function getItemTooltipFormatter(data, formatCellValue) {
|
|
272
|
-
return (params) => {
|
|
273
|
-
const seriesObj = data.series[params.seriesIndex];
|
|
274
|
-
const key = seriesObj?.originalKey || (data.categoryKeys ? data.categoryKeys[params.dataIndex] : String(params.dataIndex));
|
|
275
|
-
const valFormatted = formatCellValue(params.value, key);
|
|
276
|
-
return `<div style="text-align: center;"><b>${params.name}</b><br/>${params.marker} ${params.seriesName}<br/><b>${valFormatted}</b></div>`;
|
|
277
|
-
};
|
|
278
|
-
}
|
|
279
|
-
/**
|
|
280
|
-
* Formatter generator for 'axis' trigger strategy in tooltips.
|
|
281
|
-
*/
|
|
282
|
-
function getAxisTooltipFormatter(data, formatCellValue) {
|
|
283
|
-
return (params) => {
|
|
284
|
-
if (!params)
|
|
285
|
-
return '';
|
|
286
|
-
const items = Array.isArray(params) ? params : [params];
|
|
287
|
-
if (items.length === 0)
|
|
288
|
-
return '';
|
|
289
|
-
const firstItem = items[0];
|
|
290
|
-
let html = `<b>${firstItem.name}</b><br/>`;
|
|
291
|
-
for (const item of items) {
|
|
292
|
-
const seriesObj = data.series[item.seriesIndex];
|
|
293
|
-
if (!seriesObj)
|
|
294
|
-
continue;
|
|
295
|
-
const key = seriesObj.originalKey || (data.categoryKeys ? data.categoryKeys[item.dataIndex] : String(item.dataIndex));
|
|
296
|
-
const valFormatted = formatCellValue(item.value, key);
|
|
297
|
-
html += `${item.marker} ${item.seriesName}: <b>${valFormatted}</b><br/>`;
|
|
298
|
-
}
|
|
299
|
-
return html;
|
|
300
|
-
};
|
|
301
|
-
}
|
|
302
|
-
/**
|
|
303
|
-
* Unified tooltip formatter generator that selects the appropriate strategy based on the trigger.
|
|
304
|
-
*/
|
|
305
|
-
function getTooltipFormatter(trigger, data, formatCellValue) {
|
|
306
|
-
return trigger === 'axis'
|
|
307
|
-
? getAxisTooltipFormatter(data, formatCellValue)
|
|
308
|
-
: getItemTooltipFormatter(data, formatCellValue);
|
|
309
|
-
}
|
|
310
32
|
|
|
311
33
|
/**
|
|
312
34
|
* Inicialización centralizada de ECharts para evitar duplicación y efectos secundarios
|
|
@@ -367,75 +89,40 @@ function defaultOptionsOverrides() {
|
|
|
367
89
|
area: {
|
|
368
90
|
series: {
|
|
369
91
|
smooth: true,
|
|
370
|
-
areaStyle: {},
|
|
371
92
|
},
|
|
372
93
|
},
|
|
373
94
|
areaStack: {
|
|
374
95
|
series: {
|
|
375
96
|
smooth: true,
|
|
376
|
-
areaStyle: {},
|
|
377
|
-
stack: 'total',
|
|
378
97
|
},
|
|
379
98
|
},
|
|
380
99
|
bar: {
|
|
381
|
-
// tooltip: {},
|
|
382
100
|
series: {
|
|
383
101
|
showBackground: true,
|
|
384
102
|
},
|
|
385
103
|
},
|
|
386
104
|
barStacked: {
|
|
387
|
-
// tooltip: {
|
|
388
|
-
// trigger: 'axis',
|
|
389
|
-
// },
|
|
390
105
|
series: {
|
|
391
106
|
showBackground: false,
|
|
392
|
-
stack: 'total',
|
|
393
|
-
itemStyle: {
|
|
394
|
-
borderRadius: [0, 0, 0, 0],
|
|
395
|
-
},
|
|
396
|
-
emphasis: {
|
|
397
|
-
focus: 'series',
|
|
398
|
-
}
|
|
399
107
|
}
|
|
400
108
|
},
|
|
401
109
|
barStackedRadial: {
|
|
402
110
|
series: {
|
|
403
111
|
showBackground: false,
|
|
404
|
-
stack: 'total',
|
|
405
|
-
itemStyle: {
|
|
406
|
-
borderRadius: [0, 0, 0, 0],
|
|
407
|
-
},
|
|
408
|
-
emphasis: {
|
|
409
|
-
focus: 'series',
|
|
410
|
-
},
|
|
411
|
-
coordinateSystem: 'polar',
|
|
412
112
|
}
|
|
413
113
|
},
|
|
414
114
|
hBar: {
|
|
415
|
-
orientation: 'h',
|
|
416
|
-
// tooltip: {},
|
|
417
115
|
series: {
|
|
418
116
|
showBackground: true,
|
|
419
|
-
itemStyle: {
|
|
420
|
-
borderRadius: [0, 4, 4, 0],
|
|
421
|
-
}
|
|
422
117
|
}
|
|
423
118
|
},
|
|
424
119
|
hBarStacked: {
|
|
425
|
-
orientation: 'h',
|
|
426
|
-
// tooltip: {
|
|
427
|
-
// trigger: 'axis',
|
|
428
|
-
// },
|
|
429
120
|
series: {
|
|
430
|
-
stack: 'total',
|
|
431
121
|
showBackground: false,
|
|
432
|
-
itemStyle: {
|
|
433
|
-
borderRadius: [0, 0, 0, 0],
|
|
434
|
-
},
|
|
435
|
-
emphasis: {
|
|
436
|
-
focus: 'series',
|
|
437
|
-
}
|
|
438
122
|
}
|
|
123
|
+
},
|
|
124
|
+
ring: {
|
|
125
|
+
series: {}
|
|
439
126
|
}
|
|
440
127
|
};
|
|
441
128
|
}
|
|
@@ -460,21 +147,21 @@ class BaseEchartsComponent {
|
|
|
460
147
|
/** Formateador de valores para etiquetas y tooltips */
|
|
461
148
|
valueFormatter;
|
|
462
149
|
chartClick = new EventEmitter();
|
|
463
|
-
/** Opciones configuradas para ngx-echarts */
|
|
464
|
-
chartOptions = {};
|
|
465
150
|
/** Subject para debouncing de actualizaciones. ReplaySubject asegura no perder el primer renderizado. */
|
|
466
151
|
updateSubject = new ReplaySubject(1);
|
|
467
152
|
updateSubscription;
|
|
468
|
-
constructor() {
|
|
469
|
-
this.updateSubscription = this.updateSubject.pipe(debounceTime(150)).subscribe(options => {
|
|
470
|
-
this.updateOptions(options);
|
|
471
|
-
});
|
|
472
|
-
}
|
|
473
153
|
chartInstance;
|
|
474
154
|
currentLegendSelected = null;
|
|
475
155
|
/** Estado de selección para filtros cruzados */
|
|
476
156
|
selectedCategoryIndex = null;
|
|
477
157
|
selectedSeriesIndex = null;
|
|
158
|
+
/** Opciones configuradas para ngx-echarts */
|
|
159
|
+
chartOptions = {};
|
|
160
|
+
constructor() {
|
|
161
|
+
this.updateSubscription = this.updateSubject.pipe(debounceTime(150)).subscribe(options => {
|
|
162
|
+
this.updateOptions(options);
|
|
163
|
+
});
|
|
164
|
+
}
|
|
478
165
|
ngOnChanges(changes) {
|
|
479
166
|
this.onInputChanges(changes);
|
|
480
167
|
}
|
|
@@ -583,124 +270,371 @@ class BaseEchartsComponent {
|
|
|
583
270
|
triggerUpdate(options) {
|
|
584
271
|
this.updateSubject.next(options);
|
|
585
272
|
}
|
|
586
|
-
/**
|
|
587
|
-
* Método público para forzar el redimensionado desde el padre
|
|
588
|
-
*/
|
|
589
|
-
resize() {
|
|
590
|
-
this.chartInstance?.resize();
|
|
273
|
+
/**
|
|
274
|
+
* Método público para forzar el redimensionado desde el padre
|
|
275
|
+
*/
|
|
276
|
+
resize() {
|
|
277
|
+
this.chartInstance?.resize();
|
|
278
|
+
}
|
|
279
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: BaseEchartsComponent, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
280
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "16.1.0", version: "20.3.19", type: BaseEchartsComponent, isStandalone: true, inputs: { data: "data", optionsOverrides: ["optionsOverrides", "optionsOverrides", (values) => {
|
|
281
|
+
return merge(defaultOptionsOverrides(), values || {});
|
|
282
|
+
}], palette: "palette", colorResolver: "colorResolver", valueFormatter: "valueFormatter" }, outputs: { chartClick: "chartClick" }, viewQueries: [{ propertyName: "chartContainer", first: true, predicate: ["chartContainer"], descendants: true, static: true }], usesOnChanges: true, ngImport: i0 });
|
|
283
|
+
}
|
|
284
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: BaseEchartsComponent, decorators: [{
|
|
285
|
+
type: Directive,
|
|
286
|
+
args: [{
|
|
287
|
+
standalone: true
|
|
288
|
+
}]
|
|
289
|
+
}], ctorParameters: () => [], propDecorators: { chartContainer: [{
|
|
290
|
+
type: ViewChild,
|
|
291
|
+
args: ['chartContainer', { static: true }]
|
|
292
|
+
}], data: [{
|
|
293
|
+
type: Input
|
|
294
|
+
}], optionsOverrides: [{
|
|
295
|
+
type: Input,
|
|
296
|
+
args: [{
|
|
297
|
+
"transform": (values) => {
|
|
298
|
+
return merge(defaultOptionsOverrides(), values || {});
|
|
299
|
+
}
|
|
300
|
+
}]
|
|
301
|
+
}], palette: [{
|
|
302
|
+
type: Input
|
|
303
|
+
}], colorResolver: [{
|
|
304
|
+
type: Input
|
|
305
|
+
}], valueFormatter: [{
|
|
306
|
+
type: Input
|
|
307
|
+
}], chartClick: [{
|
|
308
|
+
type: Output
|
|
309
|
+
}] } });
|
|
310
|
+
|
|
311
|
+
/**
|
|
312
|
+
* ECharts Builder utils
|
|
313
|
+
*
|
|
314
|
+
* Biblioteca de fragmentos de configuración y tokens de diseño para asegurar
|
|
315
|
+
* una estética cohesiva en todos los gráficos de Visionaris.
|
|
316
|
+
*
|
|
317
|
+
* @see {@link VisionarisFrontEnd/docs/technical/echarts-architecture.md}
|
|
318
|
+
*/
|
|
319
|
+
// Pre-cached native formatter for performance in axis ticks
|
|
320
|
+
const compactFormatter = new Intl.NumberFormat('es-AR', {
|
|
321
|
+
notation: 'compact',
|
|
322
|
+
compactDisplay: 'short',
|
|
323
|
+
maximumFractionDigits: 1
|
|
324
|
+
});
|
|
325
|
+
/**
|
|
326
|
+
* Formats a value using native browser SI suffixes (k, M, B).
|
|
327
|
+
*/
|
|
328
|
+
function formatAxisValue(value) {
|
|
329
|
+
return compactFormatter.format(value);
|
|
330
|
+
}
|
|
331
|
+
/**
|
|
332
|
+
* Common legend configuration with scroll to prevent "cannibalization".
|
|
333
|
+
* Atomic Pattern: Provides the scrollable container with Visionaris styling.
|
|
334
|
+
*/
|
|
335
|
+
function getLegendOptions(overrides) {
|
|
336
|
+
const defaults = {
|
|
337
|
+
show: true,
|
|
338
|
+
type: 'scroll',
|
|
339
|
+
orient: 'horizontal',
|
|
340
|
+
bottom: 0,
|
|
341
|
+
left: 'center',
|
|
342
|
+
height: 60,
|
|
343
|
+
textStyle: {
|
|
344
|
+
color: '#333',
|
|
345
|
+
fontSize: EChartsTokens.fontSize,
|
|
346
|
+
fontFamily: EChartsTokens.fontFamily
|
|
347
|
+
},
|
|
348
|
+
pageButtonPosition: 'end',
|
|
349
|
+
pageIconColor: EChartsTokens.primaryColor,
|
|
350
|
+
pageIconInactiveColor: '#ccc',
|
|
351
|
+
pageIconSize: 12,
|
|
352
|
+
pageTextStyle: {
|
|
353
|
+
color: '#666'
|
|
354
|
+
}
|
|
355
|
+
};
|
|
356
|
+
return merge({}, defaults, overrides);
|
|
357
|
+
}
|
|
358
|
+
function getCategoryAxisOptions(overrides) {
|
|
359
|
+
const categories = overrides?.data ?? [];
|
|
360
|
+
const autoRotate = categories.length > 10 ? 45 : 0;
|
|
361
|
+
const defaults = {
|
|
362
|
+
type: 'category',
|
|
363
|
+
triggerEvent: true,
|
|
364
|
+
data: categories,
|
|
365
|
+
axisLabel: {
|
|
366
|
+
rotate: autoRotate,
|
|
367
|
+
interval: 0,
|
|
368
|
+
fontFamily: EChartsTokens.fontFamily,
|
|
369
|
+
color: EChartsTokens.axisColor,
|
|
370
|
+
fontSize: EChartsTokens.fontSize,
|
|
371
|
+
margin: 8,
|
|
372
|
+
fontWeight: 'normal',
|
|
373
|
+
overflow: 'break',
|
|
374
|
+
width: 1000,
|
|
375
|
+
},
|
|
376
|
+
axisLine: {
|
|
377
|
+
lineStyle: {
|
|
378
|
+
color: EChartsTokens.lineColor
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
};
|
|
382
|
+
return merge({}, defaults, overrides);
|
|
383
|
+
}
|
|
384
|
+
function getValueAxisOptions(overrides) {
|
|
385
|
+
const defaults = {
|
|
386
|
+
type: 'value',
|
|
387
|
+
splitLine: {
|
|
388
|
+
show: true,
|
|
389
|
+
lineStyle: {
|
|
390
|
+
type: 'dashed',
|
|
391
|
+
color: '#f0f0f0'
|
|
392
|
+
}
|
|
393
|
+
},
|
|
394
|
+
axisLabel: {
|
|
395
|
+
formatter: (value) => formatAxisValue(value),
|
|
396
|
+
color: EChartsTokens.axisColor,
|
|
397
|
+
fontSize: EChartsTokens.fontSize
|
|
398
|
+
}
|
|
399
|
+
};
|
|
400
|
+
return merge({}, defaults, overrides);
|
|
401
|
+
}
|
|
402
|
+
/**
|
|
403
|
+
* Callback function to dynamically position the tooltip inside the chart container boundaries.
|
|
404
|
+
*/
|
|
405
|
+
function getTooltipPositionCallback(point, params, dom, rect, size) {
|
|
406
|
+
const [x, y] = point;
|
|
407
|
+
const tooltipWidth = size?.contentSize?.[0] || dom?.offsetWidth || 150;
|
|
408
|
+
const tooltipHeight = size?.contentSize?.[1] || dom?.offsetHeight || 100;
|
|
409
|
+
const containerWidth = size?.viewSize?.[0] || 400;
|
|
410
|
+
const containerHeight = size?.viewSize?.[1] || 300;
|
|
411
|
+
const offset = 15; // Safe distance from cursor
|
|
412
|
+
let posX = x - tooltipWidth / 2;
|
|
413
|
+
let posY = y - tooltipHeight - offset; // default: above the cursor
|
|
414
|
+
// Left and right boundary checks
|
|
415
|
+
if (posX < 0) {
|
|
416
|
+
// Overflows left boundary: place to the right of the cursor
|
|
417
|
+
posX = x + offset;
|
|
418
|
+
}
|
|
419
|
+
else if (posX + tooltipWidth > containerWidth) {
|
|
420
|
+
// Overflows right boundary: place to the left of the cursor
|
|
421
|
+
posX = x - tooltipWidth - offset;
|
|
422
|
+
}
|
|
423
|
+
// Final safety clamp to container boundaries
|
|
424
|
+
if (posX + tooltipWidth > containerWidth) {
|
|
425
|
+
posX = Math.max(0, containerWidth - tooltipWidth);
|
|
426
|
+
}
|
|
427
|
+
if (posX < 0) {
|
|
428
|
+
posX = 0;
|
|
429
|
+
}
|
|
430
|
+
// Top and bottom boundary checks
|
|
431
|
+
if (posY < 0) {
|
|
432
|
+
// Overflows top boundary: place below the cursor
|
|
433
|
+
posY = y + offset;
|
|
434
|
+
}
|
|
435
|
+
else if (posY + tooltipHeight > containerHeight) {
|
|
436
|
+
// Overflows bottom boundary: place above the cursor
|
|
437
|
+
posY = y - tooltipHeight - offset;
|
|
438
|
+
}
|
|
439
|
+
// Final safety clamp to container boundaries
|
|
440
|
+
if (posY + tooltipHeight > containerHeight) {
|
|
441
|
+
posY = Math.max(0, containerHeight - tooltipHeight);
|
|
442
|
+
}
|
|
443
|
+
if (posY < 0) {
|
|
444
|
+
posY = 0;
|
|
591
445
|
}
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
446
|
+
return [posX, posY];
|
|
447
|
+
}
|
|
448
|
+
/**
|
|
449
|
+
* Common Tooltip configuration.
|
|
450
|
+
* Atomic Pattern: Enforces consistent glassmorphism and pointer styles.
|
|
451
|
+
*/
|
|
452
|
+
function getTooltipOptions(overrides) {
|
|
453
|
+
const trigger = overrides?.trigger || 'axis';
|
|
454
|
+
const isAxis = trigger === 'axis';
|
|
455
|
+
const defaults = {
|
|
456
|
+
show: true,
|
|
457
|
+
trigger: trigger,
|
|
458
|
+
position: getTooltipPositionCallback,
|
|
459
|
+
backgroundColor: EChartsTokens.tooltipBg,
|
|
460
|
+
borderColor: '#eee',
|
|
461
|
+
borderWidth: 1,
|
|
462
|
+
textStyle: {
|
|
463
|
+
color: '#333',
|
|
464
|
+
fontSize: 12
|
|
465
|
+
},
|
|
466
|
+
extraCssText: 'box-shadow: 0 0 10px rgba(0,0,0,0.1); border-radius: 8px;',
|
|
467
|
+
...(isAxis ? {
|
|
468
|
+
axisPointer: {
|
|
469
|
+
type: 'shadow'
|
|
470
|
+
}
|
|
471
|
+
} : {})
|
|
472
|
+
};
|
|
473
|
+
return merge({}, defaults, overrides);
|
|
474
|
+
}
|
|
475
|
+
/**
|
|
476
|
+
* Applies a visual selection effect to line-based series.
|
|
477
|
+
* Highlights the selected series and point, and dims everything else.
|
|
478
|
+
*
|
|
479
|
+
* @param series The series array to modify
|
|
480
|
+
* @param selectedCategoryIndex Index of the selected category
|
|
481
|
+
* @param selectedSeriesIndex Index of the selected series
|
|
482
|
+
* @returns Modified series array
|
|
483
|
+
*/
|
|
484
|
+
function applyLineSelectionStyle$1(series, selectedCategoryIndex, selectedSeriesIndex) {
|
|
485
|
+
if (selectedCategoryIndex === null || !series)
|
|
486
|
+
return series;
|
|
487
|
+
return series.map((s, sIdx) => {
|
|
488
|
+
const isSelectedSeries = sIdx === selectedSeriesIndex;
|
|
489
|
+
// Serie seleccionada: Línea con opacidad 1 para que destaque la tendencia.
|
|
490
|
+
// Serie NO seleccionada: Opacidad 0.20 para atenuar fuertemente.
|
|
491
|
+
const seriesOpacity = isSelectedSeries ? 1 : 0.20;
|
|
492
|
+
return {
|
|
493
|
+
...s,
|
|
494
|
+
emphasis: {
|
|
495
|
+
disabled: true // Deshabilitar el énfasis (hover) cuando hay una selección activa
|
|
496
|
+
},
|
|
497
|
+
itemStyle: {
|
|
498
|
+
...s.itemStyle,
|
|
499
|
+
opacity: seriesOpacity
|
|
500
|
+
},
|
|
501
|
+
lineStyle: {
|
|
502
|
+
...s.lineStyle,
|
|
503
|
+
opacity: seriesOpacity
|
|
504
|
+
},
|
|
505
|
+
...(s.areaStyle ? {
|
|
506
|
+
areaStyle: {
|
|
507
|
+
...s.areaStyle,
|
|
508
|
+
opacity: isSelectedSeries ? 0.6 : 0.1
|
|
509
|
+
}
|
|
510
|
+
} : {}),
|
|
511
|
+
// Personalizamos los puntos individualmente
|
|
512
|
+
data: (s.data || []).map((val, idx) => {
|
|
513
|
+
const isSelectedPoint = isSelectedSeries && idx === selectedCategoryIndex;
|
|
514
|
+
const isOtherPointInSelectedSeries = isSelectedSeries && idx !== selectedCategoryIndex;
|
|
515
|
+
const originalPoint = (val && typeof val === 'object') ? val : { value: val };
|
|
516
|
+
if (isSelectedPoint) {
|
|
517
|
+
return {
|
|
518
|
+
...originalPoint,
|
|
519
|
+
z: 10, // Asegurar que el punto seleccionado esté por encima de los demás
|
|
520
|
+
itemStyle: {
|
|
521
|
+
...originalPoint.itemStyle,
|
|
522
|
+
opacity: 1,
|
|
523
|
+
borderWidth: 2,
|
|
524
|
+
borderColor: '#fff',
|
|
525
|
+
shadowBlur: 10,
|
|
526
|
+
shadowColor: 'rgba(0,0,0,0.5)'
|
|
527
|
+
},
|
|
528
|
+
symbolSize: 12
|
|
529
|
+
};
|
|
530
|
+
}
|
|
531
|
+
else if (isOtherPointInSelectedSeries) {
|
|
532
|
+
// Puntos de la serie seleccionada que NO son el clicado: un poco más pequeños y traslúcidos
|
|
533
|
+
return {
|
|
534
|
+
...originalPoint,
|
|
535
|
+
itemStyle: {
|
|
536
|
+
...originalPoint.itemStyle,
|
|
537
|
+
opacity: 0.5
|
|
538
|
+
},
|
|
539
|
+
symbolSize: 6
|
|
540
|
+
};
|
|
541
|
+
}
|
|
542
|
+
// Puntos de otras series o por defecto
|
|
543
|
+
return val;
|
|
544
|
+
})
|
|
545
|
+
};
|
|
546
|
+
});
|
|
547
|
+
}
|
|
548
|
+
/**
|
|
549
|
+
* Formatter generator for 'item' trigger strategy in tooltips.
|
|
550
|
+
*/
|
|
551
|
+
function getItemTooltipFormatter(data, formatCellValue) {
|
|
552
|
+
return (params) => {
|
|
553
|
+
const seriesObj = data.series[params.seriesIndex];
|
|
554
|
+
const key = seriesObj?.originalKey || (data.categoryKeys ? data.categoryKeys[params.dataIndex] : String(params.dataIndex));
|
|
555
|
+
const valFormatted = formatCellValue(params.value, key);
|
|
556
|
+
return `<div style="text-align: center;"><b>${params.name}</b><br/>${params.marker} ${params.seriesName}<br/><b>${valFormatted}</b></div>`;
|
|
557
|
+
};
|
|
558
|
+
}
|
|
559
|
+
/**
|
|
560
|
+
* Formatter generator for 'axis' trigger strategy in tooltips.
|
|
561
|
+
*/
|
|
562
|
+
function getAxisTooltipFormatter(data, formatCellValue) {
|
|
563
|
+
return (params) => {
|
|
564
|
+
if (!params)
|
|
565
|
+
return '';
|
|
566
|
+
const items = Array.isArray(params) ? params : [params];
|
|
567
|
+
if (items.length === 0)
|
|
568
|
+
return '';
|
|
569
|
+
const firstItem = items[0];
|
|
570
|
+
let html = `<b>${firstItem.name}</b><br/>`;
|
|
571
|
+
for (const item of items) {
|
|
572
|
+
const seriesObj = data.series[item.seriesIndex];
|
|
573
|
+
if (!seriesObj)
|
|
574
|
+
continue;
|
|
575
|
+
const key = seriesObj.originalKey || (data.categoryKeys ? data.categoryKeys[item.dataIndex] : String(item.dataIndex));
|
|
576
|
+
const valFormatted = formatCellValue(item.value, key);
|
|
577
|
+
html += `${item.marker} ${item.seriesName}: <b>${valFormatted}</b><br/>`;
|
|
578
|
+
}
|
|
579
|
+
return html;
|
|
580
|
+
};
|
|
581
|
+
}
|
|
582
|
+
/**
|
|
583
|
+
* Unified tooltip formatter generator that selects the appropriate strategy based on the trigger.
|
|
584
|
+
*/
|
|
585
|
+
function getTooltipFormatter(trigger, data, formatCellValue) {
|
|
586
|
+
return trigger === 'axis'
|
|
587
|
+
? getAxisTooltipFormatter(data, formatCellValue)
|
|
588
|
+
: getItemTooltipFormatter(data, formatCellValue);
|
|
589
|
+
}
|
|
590
|
+
function getCommons(opts) {
|
|
591
|
+
const palette = opts?.palette ?? getDefaultPalette();
|
|
592
|
+
const common = {
|
|
593
|
+
backgroundColor: 'transparent',
|
|
594
|
+
textStyle: {
|
|
595
|
+
fontFamily: "'Inter', 'Roboto', 'Open Sans', sans-serif",
|
|
596
|
+
},
|
|
597
|
+
grid: {
|
|
598
|
+
left: '3%',
|
|
599
|
+
right: '4%',
|
|
600
|
+
bottom: '15%',
|
|
601
|
+
top: '20px',
|
|
602
|
+
containLabel: true,
|
|
603
|
+
},
|
|
604
|
+
};
|
|
605
|
+
// Aplicar paleta global: Prioridad Palette Inyectada > Default Visionaris
|
|
606
|
+
common.color = (palette && palette.length > 0) ? palette : getDefaultPalette();
|
|
607
|
+
return common;
|
|
596
608
|
}
|
|
597
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: BaseEchartsComponent, decorators: [{
|
|
598
|
-
type: Directive,
|
|
599
|
-
args: [{
|
|
600
|
-
standalone: true
|
|
601
|
-
}]
|
|
602
|
-
}], ctorParameters: () => [], propDecorators: { chartContainer: [{
|
|
603
|
-
type: ViewChild,
|
|
604
|
-
args: ['chartContainer', { static: true }]
|
|
605
|
-
}], data: [{
|
|
606
|
-
type: Input
|
|
607
|
-
}], optionsOverrides: [{
|
|
608
|
-
type: Input,
|
|
609
|
-
args: [{
|
|
610
|
-
"transform": (values) => {
|
|
611
|
-
return merge(defaultOptionsOverrides(), values || {});
|
|
612
|
-
}
|
|
613
|
-
}]
|
|
614
|
-
}], palette: [{
|
|
615
|
-
type: Input
|
|
616
|
-
}], colorResolver: [{
|
|
617
|
-
type: Input
|
|
618
|
-
}], valueFormatter: [{
|
|
619
|
-
type: Input
|
|
620
|
-
}], chartClick: [{
|
|
621
|
-
type: Output
|
|
622
|
-
}] } });
|
|
623
609
|
|
|
624
610
|
/**
|
|
625
|
-
*
|
|
611
|
+
* RingBuilder
|
|
626
612
|
*
|
|
627
|
-
*
|
|
628
|
-
* Implementa lógica compartida de paletas y opciones comunes.
|
|
613
|
+
* Builder concreto para el grafico de Ring.
|
|
629
614
|
*
|
|
630
|
-
* @see {@link vs-echarts/docs/internal-architecture.md}
|
|
631
615
|
*/
|
|
632
|
-
class
|
|
616
|
+
class RingBuilder {
|
|
617
|
+
baseProduct;
|
|
633
618
|
valueFormatter = (value) => value.toLocaleString();
|
|
634
619
|
palette = [];
|
|
635
|
-
// TODO: Hay que implementar un valor por defecto.
|
|
636
620
|
colorResolver;
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
*/
|
|
641
|
-
setValueFormatter(formatter) {
|
|
642
|
-
if (formatter) {
|
|
643
|
-
this.valueFormatter = formatter;
|
|
644
|
-
}
|
|
645
|
-
}
|
|
646
|
-
/**
|
|
647
|
-
* Permite inyectar una paleta de colores básica.
|
|
648
|
-
*/
|
|
649
|
-
setPalette(palette) {
|
|
650
|
-
if (palette) {
|
|
651
|
-
this.palette = palette;
|
|
652
|
-
}
|
|
621
|
+
result = {};
|
|
622
|
+
constructor(baseProduct) {
|
|
623
|
+
this.baseProduct = baseProduct;
|
|
653
624
|
}
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
*/
|
|
657
|
-
setColorResolver(resolver) {
|
|
658
|
-
if (resolver) {
|
|
659
|
-
this.colorResolver = resolver;
|
|
660
|
-
}
|
|
625
|
+
reset() {
|
|
626
|
+
this.result = {};
|
|
661
627
|
}
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
* TODO: particionar en configuraciones concretas con sus
|
|
666
|
-
* respectivos overrides.
|
|
667
|
-
*/
|
|
668
|
-
getCommonOptions(overrides) {
|
|
669
|
-
const common = {
|
|
670
|
-
backgroundColor: 'transparent',
|
|
671
|
-
textStyle: {
|
|
672
|
-
fontFamily: "'Inter', 'Roboto', 'Open Sans', sans-serif"
|
|
673
|
-
},
|
|
674
|
-
grid: {
|
|
675
|
-
left: '3%',
|
|
676
|
-
right: '4%',
|
|
677
|
-
bottom: '15%',
|
|
678
|
-
top: '20px',
|
|
679
|
-
containLabel: true
|
|
680
|
-
}
|
|
628
|
+
addCommons() {
|
|
629
|
+
const opts = {
|
|
630
|
+
palette: this.palette,
|
|
681
631
|
};
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
return common;
|
|
685
|
-
}
|
|
686
|
-
/**
|
|
687
|
-
* Formatea un valor utilizando el callback inyectado.
|
|
688
|
-
*/
|
|
689
|
-
formatCellValue(value, key) {
|
|
690
|
-
return this.valueFormatter(value, key);
|
|
632
|
+
const common = getCommons(opts);
|
|
633
|
+
merge(this.result, common);
|
|
691
634
|
}
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
/**
|
|
695
|
-
* RingBuilder
|
|
696
|
-
*
|
|
697
|
-
* Especializado en construir opciones para gráficos de tipo Ring (Donas concéntricas).
|
|
698
|
-
* @see {@link vs-echarts/docs/charts/ring-patterns.md}
|
|
699
|
-
*/
|
|
700
|
-
class RingBuilder extends BaseEchartBuilder {
|
|
701
|
-
build(data, overrides) {
|
|
635
|
+
addSeries(data, overrides) {
|
|
702
636
|
if (!data || !data.series.length)
|
|
703
|
-
return
|
|
637
|
+
return;
|
|
704
638
|
const totalRings = data.series.length; // Cada serie es un anillo
|
|
705
639
|
// Configuración dinámica de radios y márgenes
|
|
706
640
|
const margin = totalRings > 1 ? Math.max(0.5, 2.5 - (totalRings * 0.1)) : 0;
|
|
@@ -718,81 +652,194 @@ class RingBuilder extends BaseEchartBuilder {
|
|
|
718
652
|
value: s.data[catIndex],
|
|
719
653
|
originalMeassureKey: s.originalKey || (data.categoryKeys ? data.categoryKeys[catIndex] : '')
|
|
720
654
|
}));
|
|
721
|
-
const
|
|
655
|
+
const dynamicRingSeriesOptions = {
|
|
722
656
|
name: s.name,
|
|
723
|
-
type: 'pie',
|
|
724
657
|
radius: [`${inner}%`, `${outer}%`],
|
|
725
|
-
center: ['50%', '50%'],
|
|
726
|
-
avoidLabelOverlap: true,
|
|
727
|
-
minAngle: 3,
|
|
728
|
-
selectedMode: 'single',
|
|
729
|
-
selectedOffset: 4,
|
|
730
658
|
itemStyle: {
|
|
731
659
|
borderRadius: borderRadius,
|
|
732
|
-
|
|
733
|
-
borderWidth: borderWidth
|
|
660
|
+
borderWidth: borderWidth,
|
|
734
661
|
},
|
|
735
|
-
label: { show: false },
|
|
736
662
|
emphasis: {
|
|
737
|
-
scale: true,
|
|
738
|
-
scaleSize: 2,
|
|
739
663
|
itemStyle: {
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
}
|
|
664
|
+
borderWidth: borderWidth,
|
|
665
|
+
},
|
|
743
666
|
},
|
|
744
667
|
select: {
|
|
745
668
|
itemStyle: {
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
}
|
|
669
|
+
borderWidth: borderWidth,
|
|
670
|
+
},
|
|
749
671
|
},
|
|
750
|
-
animationType: 'scale',
|
|
751
|
-
animationEasing: 'elasticOut',
|
|
752
672
|
data: pieData,
|
|
753
|
-
id: `ring_${ringIndex}
|
|
673
|
+
id: `ring_${ringIndex}`,
|
|
754
674
|
};
|
|
675
|
+
const seriesOption = merge(dynamicRingSeriesOptions, overrides);
|
|
755
676
|
// Inyectar el resolver de color si existe
|
|
756
|
-
if (this.colorResolver) {
|
|
677
|
+
if (this.colorResolver && seriesOption.itemStyle) {
|
|
757
678
|
seriesOption.itemStyle.color = this.colorResolver;
|
|
758
679
|
}
|
|
759
680
|
return seriesOption;
|
|
760
681
|
});
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
682
|
+
this.result.series = series;
|
|
683
|
+
}
|
|
684
|
+
addGraphic() {
|
|
685
|
+
// Add graphic element for the center KPI
|
|
686
|
+
this.result.graphic = [{
|
|
687
|
+
id: 'center-kpi',
|
|
688
|
+
type: 'text',
|
|
689
|
+
left: 'center',
|
|
690
|
+
top: 'middle',
|
|
691
|
+
z: 100,
|
|
692
|
+
transition: ['style'],
|
|
693
|
+
style: {
|
|
694
|
+
text: '',
|
|
695
|
+
fontSize: 22,
|
|
696
|
+
fontWeight: 'bold',
|
|
697
|
+
fill: '#333',
|
|
698
|
+
stroke: '#fff',
|
|
699
|
+
lineWidth: 1,
|
|
700
|
+
paintOrder: 'stroke',
|
|
701
|
+
textAlign: 'center',
|
|
702
|
+
textVerticalAlign: 'middle',
|
|
703
|
+
opacity: 0,
|
|
704
|
+
},
|
|
705
|
+
}];
|
|
706
|
+
}
|
|
707
|
+
addTooltip(data, overrides) {
|
|
708
|
+
const totalRings = data.series.length;
|
|
709
|
+
merge(overrides, {
|
|
710
|
+
formatter: (params) => {
|
|
711
|
+
const key = params.data.originalMeassureKey || '';
|
|
712
|
+
const valFormatted = this.formatCellValue(params.value, key);
|
|
713
|
+
const seriesHeader = totalRings > 1 ? `<b>${params.seriesName}</b><br/>` : '';
|
|
714
|
+
return `${seriesHeader}${params.name}<br/>${params.marker} <b>${valFormatted}</b> (${params.percent}%)`;
|
|
772
715
|
},
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
}
|
|
716
|
+
});
|
|
717
|
+
const tooltip = getTooltipOptions(overrides);
|
|
718
|
+
this.result.tooltip = tooltip;
|
|
719
|
+
}
|
|
720
|
+
addLegend() {
|
|
721
|
+
this.result.legend = getLegendOptions();
|
|
722
|
+
}
|
|
723
|
+
// No-ops for ring charts
|
|
724
|
+
addPolar() { }
|
|
725
|
+
addXAxis(data, overrides, type) { }
|
|
726
|
+
addYAxis(data, overrides, type) { }
|
|
727
|
+
addRadiusAxis(data, overrides) { }
|
|
728
|
+
addAngleAxis(data, overrides) { }
|
|
729
|
+
// Callback setters
|
|
730
|
+
setValueFormatter(formatter) {
|
|
731
|
+
if (formatter) {
|
|
732
|
+
this.valueFormatter = formatter;
|
|
733
|
+
}
|
|
734
|
+
}
|
|
735
|
+
setPalette(palette) {
|
|
736
|
+
if (palette) {
|
|
737
|
+
this.palette = palette;
|
|
738
|
+
}
|
|
739
|
+
}
|
|
740
|
+
setColorResolver(resolver) {
|
|
741
|
+
if (resolver) {
|
|
742
|
+
this.colorResolver = resolver;
|
|
743
|
+
}
|
|
744
|
+
}
|
|
745
|
+
getResult() {
|
|
746
|
+
return this.result;
|
|
747
|
+
}
|
|
748
|
+
formatCellValue(value, key) {
|
|
749
|
+
return this.valueFormatter(value, key);
|
|
750
|
+
}
|
|
751
|
+
}
|
|
752
|
+
|
|
753
|
+
/**
|
|
754
|
+
* Director de Builds.
|
|
755
|
+
*/
|
|
756
|
+
class VSECDirector {
|
|
757
|
+
builder = undefined;
|
|
758
|
+
constructor(builder) {
|
|
759
|
+
this.builder = builder;
|
|
760
|
+
}
|
|
761
|
+
makeBar(data, overrides, opts = {}) {
|
|
762
|
+
const { valueFormatter = undefined, palette = undefined, colorResolver = undefined, axisTypes = {
|
|
763
|
+
x: 'category',
|
|
764
|
+
y: 'value',
|
|
765
|
+
// TODO agregar radius y angle axis
|
|
766
|
+
} } = opts;
|
|
767
|
+
this.builder.reset();
|
|
768
|
+
// El orden importa, primero callbaks y despues componentes.
|
|
769
|
+
//chart callbacks
|
|
770
|
+
this.builder.setValueFormatter(valueFormatter);
|
|
771
|
+
this.builder.setPalette(palette);
|
|
772
|
+
this.builder.setValueFormatter(valueFormatter);
|
|
773
|
+
const product = this.builder.baseProduct;
|
|
774
|
+
const seriesOverrides = merge$1(product.baseOptions.series, overrides[product.chartKey].series);
|
|
775
|
+
// chart components
|
|
776
|
+
this.builder.addCommons();
|
|
777
|
+
this.builder.addSeries(data, seriesOverrides);
|
|
778
|
+
this.builder.addXAxis(data, overrides.axis, axisTypes.x);
|
|
779
|
+
this.builder.addYAxis(data, overrides.axis, axisTypes.y);
|
|
780
|
+
this.builder.addTooltip(data, overrides.tooltip);
|
|
781
|
+
this.builder.addLegend();
|
|
782
|
+
}
|
|
783
|
+
makeBarRadial(data, overrides, opts = {}) {
|
|
784
|
+
const { valueFormatter = undefined, palette = undefined, colorResolver = undefined, axisTypes = {
|
|
785
|
+
x: 'category',
|
|
786
|
+
y: 'value',
|
|
787
|
+
// TODO agregar radius y angle axis
|
|
788
|
+
} } = opts;
|
|
789
|
+
this.builder.reset();
|
|
790
|
+
// El orden importa, primero callbaks y despues componentes.
|
|
791
|
+
//chart callbacks
|
|
792
|
+
this.builder.setValueFormatter(valueFormatter);
|
|
793
|
+
this.builder.setPalette(palette);
|
|
794
|
+
this.builder.setValueFormatter(valueFormatter);
|
|
795
|
+
const product = this.builder.baseProduct;
|
|
796
|
+
const seriesOverrides = merge$1({}, product.baseOptions.series, overrides[product.chartKey].series);
|
|
797
|
+
// chart components
|
|
798
|
+
this.builder.addCommons();
|
|
799
|
+
this.builder.addSeries(data, seriesOverrides);
|
|
800
|
+
this.builder.addPolar();
|
|
801
|
+
this.builder.addAngleAxis(data, overrides['axis']);
|
|
802
|
+
this.builder.addRadiusAxis(data, overrides['axis']);
|
|
803
|
+
this.builder.addTooltip(data, overrides.tooltip);
|
|
804
|
+
this.builder.addLegend();
|
|
805
|
+
}
|
|
806
|
+
makeLine(data, overrides, opts = {}) {
|
|
807
|
+
const { valueFormatter = undefined, palette = undefined, colorResolver = undefined, axisTypes = {
|
|
808
|
+
x: 'category',
|
|
809
|
+
y: 'value',
|
|
810
|
+
// TODO agregar radius y angle axis
|
|
811
|
+
} } = opts;
|
|
812
|
+
this.builder.reset();
|
|
813
|
+
// El orden importa, primero callbaks y despues componentes.
|
|
814
|
+
//chart callbacks
|
|
815
|
+
this.builder.setValueFormatter(valueFormatter);
|
|
816
|
+
this.builder.setPalette(palette);
|
|
817
|
+
this.builder.setValueFormatter(valueFormatter);
|
|
818
|
+
const product = this.builder.baseProduct;
|
|
819
|
+
const seriesOverrides = merge$1({}, product.baseOptions.series, overrides[product.chartKey].series);
|
|
820
|
+
// chart components
|
|
821
|
+
this.builder.addCommons();
|
|
822
|
+
this.builder.addSeries(data, seriesOverrides);
|
|
823
|
+
this.builder.addXAxis(data, overrides.axis, axisTypes.x);
|
|
824
|
+
this.builder.addYAxis(data, overrides.axis, axisTypes.y);
|
|
825
|
+
this.builder.addTooltip(data, overrides.tooltip);
|
|
826
|
+
this.builder.addLegend();
|
|
827
|
+
}
|
|
828
|
+
makeRing(data, overrides, opts = {}) {
|
|
829
|
+
const { valueFormatter = undefined, palette = undefined, colorResolver = undefined, } = opts;
|
|
830
|
+
this.builder.reset();
|
|
831
|
+
// El orden importa, primero callbacks y despues componentes.
|
|
832
|
+
this.builder.setValueFormatter(valueFormatter);
|
|
833
|
+
this.builder.setPalette(palette);
|
|
834
|
+
this.builder.setColorResolver(colorResolver);
|
|
835
|
+
const product = this.builder.baseProduct;
|
|
836
|
+
const seriesOverrides = merge$1({}, product.baseOptions.series, overrides[product.chartKey].series);
|
|
837
|
+
// chart components
|
|
838
|
+
this.builder.addCommons();
|
|
839
|
+
this.builder.addSeries(data, seriesOverrides);
|
|
840
|
+
this.builder.addGraphic();
|
|
841
|
+
this.builder.addTooltip(data, overrides.tooltip);
|
|
842
|
+
this.builder.addLegend();
|
|
796
843
|
}
|
|
797
844
|
}
|
|
798
845
|
|
|
@@ -803,14 +850,49 @@ class RingBuilder extends BaseEchartBuilder {
|
|
|
803
850
|
* @see {@link vs-echarts/docs/charts/ring-patterns.md}
|
|
804
851
|
*/
|
|
805
852
|
class EchartsRingComponent extends BaseEchartsComponent {
|
|
853
|
+
baseSeriesOptions = {
|
|
854
|
+
type: 'pie',
|
|
855
|
+
center: ['50%', '50%'],
|
|
856
|
+
avoidLabelOverlap: true,
|
|
857
|
+
minAngle: 3,
|
|
858
|
+
selectedMode: 'single',
|
|
859
|
+
selectedOffset: 4,
|
|
860
|
+
itemStyle: {
|
|
861
|
+
borderColor: '#fff',
|
|
862
|
+
},
|
|
863
|
+
label: { show: false },
|
|
864
|
+
emphasis: {
|
|
865
|
+
scale: true,
|
|
866
|
+
scaleSize: 2,
|
|
867
|
+
itemStyle: {
|
|
868
|
+
borderColor: '#fff',
|
|
869
|
+
},
|
|
870
|
+
},
|
|
871
|
+
select: {
|
|
872
|
+
itemStyle: {
|
|
873
|
+
borderColor: '#fff',
|
|
874
|
+
},
|
|
875
|
+
},
|
|
876
|
+
animationType: 'scale',
|
|
877
|
+
animationEasing: 'elasticOut',
|
|
878
|
+
};
|
|
879
|
+
baseProduct = {
|
|
880
|
+
chartKey: 'ring',
|
|
881
|
+
baseOptions: {
|
|
882
|
+
series: this.baseSeriesOptions,
|
|
883
|
+
}
|
|
884
|
+
};
|
|
885
|
+
builder = new RingBuilder(this.baseProduct);
|
|
886
|
+
director = new VSECDirector(this.builder);
|
|
806
887
|
lastSelectedSeriesIndex = null;
|
|
807
888
|
lastSelectedDataIndex = null;
|
|
808
889
|
selectedPercent = null;
|
|
809
890
|
currentGraphicText = '';
|
|
810
|
-
builder;
|
|
811
891
|
constructor() {
|
|
812
892
|
super();
|
|
813
|
-
|
|
893
|
+
}
|
|
894
|
+
make(makeOpts) {
|
|
895
|
+
this.director.makeRing(this.data, this.optionsOverrides, makeOpts);
|
|
814
896
|
}
|
|
815
897
|
onInputChanges(changes) {
|
|
816
898
|
// Reset selection only if data changed
|
|
@@ -897,15 +979,14 @@ class EchartsRingComponent extends BaseEchartsComponent {
|
|
|
897
979
|
if (!this.data)
|
|
898
980
|
return;
|
|
899
981
|
// 1. Configuramos el builder (Formateadores, Colores, etc se manejan en la base)
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
this.
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
this.builder.setColorResolver(this.colorResolver);
|
|
982
|
+
const makeOpts = {
|
|
983
|
+
valueFormatter: this.valueFormatter,
|
|
984
|
+
palette: this.palette,
|
|
985
|
+
colorResolver: this.colorResolver,
|
|
986
|
+
};
|
|
987
|
+
this.make(makeOpts);
|
|
907
988
|
// 2. Obtenemos las bases del chart usando el builder
|
|
908
|
-
let options = this.builder.
|
|
989
|
+
let options = this.builder.getResult();
|
|
909
990
|
// 3. Persistencia de GRAPHIC (KPI central)
|
|
910
991
|
if (options.graphic && Array.isArray(options.graphic)) {
|
|
911
992
|
const graphic = options.graphic[0];
|
|
@@ -948,359 +1029,276 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImpo
|
|
|
948
1029
|
}], ctorParameters: () => [] });
|
|
949
1030
|
|
|
950
1031
|
/**
|
|
951
|
-
*
|
|
1032
|
+
* Builder principal.
|
|
1033
|
+
*
|
|
1034
|
+
* Es muy completo, tiene soporte para ejes y sistema cartesiano polar.
|
|
952
1035
|
*
|
|
953
|
-
*
|
|
954
|
-
* @see {@link vs-echarts/docs/charts/vertical-bands-patterns.md}
|
|
1036
|
+
* Puede verse utilizado en graficos como Lineas y Bars. Siempre que se pueda priorizar utilizar este.
|
|
955
1037
|
*/
|
|
956
|
-
class
|
|
957
|
-
|
|
958
|
-
|
|
1038
|
+
class EChartBuilder {
|
|
1039
|
+
baseProduct = undefined;
|
|
1040
|
+
valueFormatter = (value) => value.toLocaleString();
|
|
1041
|
+
palette = [];
|
|
1042
|
+
// TODO: Hay que implementar un valor por defecto.
|
|
1043
|
+
colorResolver;
|
|
1044
|
+
result = {};
|
|
1045
|
+
constructor(baseProduct) {
|
|
1046
|
+
this.baseProduct = baseProduct;
|
|
1047
|
+
}
|
|
1048
|
+
reset() {
|
|
1049
|
+
this.result = {};
|
|
1050
|
+
}
|
|
1051
|
+
addCommons() {
|
|
1052
|
+
const opts = {
|
|
1053
|
+
palette: this.palette,
|
|
1054
|
+
};
|
|
1055
|
+
merge$1(this.result, getCommons(opts));
|
|
959
1056
|
}
|
|
960
|
-
|
|
1057
|
+
/**
|
|
1058
|
+
*
|
|
1059
|
+
* @param data
|
|
1060
|
+
* @param overrides
|
|
1061
|
+
* @returns
|
|
1062
|
+
*/
|
|
1063
|
+
addSeries(data, overrides) {
|
|
961
1064
|
if (!data || !data.series.length)
|
|
962
|
-
return
|
|
1065
|
+
return;
|
|
963
1066
|
const series = data.series.map((s) => {
|
|
964
|
-
const
|
|
1067
|
+
const dynamicOverrides = {
|
|
965
1068
|
name: s.name,
|
|
966
|
-
type: 'bar',
|
|
967
|
-
barMaxWidth: 50,
|
|
968
|
-
barGap: '15%',
|
|
969
|
-
barCategoryGap: '35%',
|
|
970
|
-
animation: true,
|
|
971
|
-
animationDuration: 1000,
|
|
972
|
-
animationEasing: 'cubicOut',
|
|
973
|
-
itemStyle: {
|
|
974
|
-
borderRadius: [4, 4, 0, 0]
|
|
975
|
-
},
|
|
976
1069
|
data: s.data,
|
|
977
|
-
emphasis: {
|
|
978
|
-
focus: 'none'
|
|
979
|
-
},
|
|
980
|
-
blur: {
|
|
981
|
-
itemStyle: {
|
|
982
|
-
opacity: 0.2
|
|
983
|
-
}
|
|
984
|
-
},
|
|
985
|
-
select: {
|
|
986
|
-
itemStyle: {
|
|
987
|
-
opacity: 1,
|
|
988
|
-
shadowBlur: 10,
|
|
989
|
-
shadowColor: 'rgba(0,0,0,0.3)'
|
|
990
|
-
}
|
|
991
|
-
},
|
|
992
1070
|
label: {
|
|
993
|
-
show: false,
|
|
994
|
-
position: 'top',
|
|
995
1071
|
formatter: (params) => {
|
|
996
1072
|
const key = s.originalKey || (data.categoryKeys ? data.categoryKeys[params.dataIndex] : String(params.dataIndex));
|
|
997
1073
|
return this.formatCellValue(params.value, key);
|
|
998
1074
|
}
|
|
999
1075
|
}
|
|
1000
1076
|
};
|
|
1077
|
+
const seriesOption = merge$1(dynamicOverrides, overrides);
|
|
1001
1078
|
// Inyectar el resolver de color si existe
|
|
1002
|
-
if (this.colorResolver) {
|
|
1079
|
+
if (this.colorResolver && seriesOption.itemStyle) {
|
|
1003
1080
|
seriesOption.itemStyle.color = this.colorResolver;
|
|
1004
1081
|
}
|
|
1005
1082
|
return seriesOption;
|
|
1006
1083
|
});
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1084
|
+
this.result.series = series;
|
|
1085
|
+
}
|
|
1086
|
+
/**
|
|
1087
|
+
* TODO: Mejorar funcion, no me convence como se implemento el tooltip formatter.
|
|
1088
|
+
* @param data
|
|
1089
|
+
* @param overrides
|
|
1090
|
+
*/
|
|
1091
|
+
addTooltip(data, overrides) {
|
|
1092
|
+
// inyecto formateador a overrides de tooltip
|
|
1093
|
+
merge$1(overrides, {
|
|
1094
|
+
formatter: getTooltipFormatter(overrides.trigger, data, this.formatCellValue.bind(this)),
|
|
1095
|
+
});
|
|
1096
|
+
const tooltip = getTooltipOptions(overrides);
|
|
1097
|
+
this.result.tooltip = tooltip;
|
|
1098
|
+
}
|
|
1099
|
+
addPolar() {
|
|
1100
|
+
const polar = [];
|
|
1101
|
+
polar.push({
|
|
1102
|
+
radius: '65%',
|
|
1103
|
+
center: ["50%", "44%"],
|
|
1104
|
+
});
|
|
1105
|
+
this.result.polar = polar;
|
|
1106
|
+
}
|
|
1107
|
+
addXAxis(data, overrides, type = 'category') {
|
|
1108
|
+
const xAxis = [];
|
|
1109
|
+
const categoryAxisOptions = this.getCategoryAxisOptions(data, overrides);
|
|
1110
|
+
const valueAxisOptions = this.getValueAxisOptions(data, overrides);
|
|
1111
|
+
if (type == 'category') {
|
|
1112
|
+
xAxis.push(categoryAxisOptions);
|
|
1113
|
+
}
|
|
1114
|
+
else if (type == 'value') {
|
|
1115
|
+
xAxis.push(valueAxisOptions);
|
|
1116
|
+
}
|
|
1117
|
+
this.result.xAxis = xAxis;
|
|
1118
|
+
}
|
|
1119
|
+
addYAxis(data, overrides, type = 'value') {
|
|
1120
|
+
const yAxis = [];
|
|
1121
|
+
const categoryAxisOptions = this.getCategoryAxisOptions(data, overrides);
|
|
1122
|
+
const valueAxisOptions = this.getValueAxisOptions(data, overrides);
|
|
1123
|
+
if (type == 'category') {
|
|
1124
|
+
yAxis.push(categoryAxisOptions);
|
|
1125
|
+
}
|
|
1126
|
+
else if (type == 'value') {
|
|
1127
|
+
yAxis.push(valueAxisOptions);
|
|
1128
|
+
}
|
|
1129
|
+
this.result.yAxis = yAxis;
|
|
1130
|
+
}
|
|
1131
|
+
addRadiusAxis(data, overrides) {
|
|
1132
|
+
const radiusAxis = [];
|
|
1133
|
+
/** estilos exclusivos hardcodeados para el eje de valores del sistema de coordenadas polar*/
|
|
1134
|
+
const radiusAxisOverrides = {
|
|
1135
|
+
axisTick: {
|
|
1136
|
+
show: false,
|
|
1021
1137
|
},
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1138
|
+
axisLabel: {
|
|
1139
|
+
margin: 2,
|
|
1140
|
+
fontSize: 8,
|
|
1141
|
+
align: 'right',
|
|
1142
|
+
rotate: 20,
|
|
1143
|
+
verticalAlign: 'top',
|
|
1144
|
+
},
|
|
1145
|
+
axisLine: {
|
|
1146
|
+
lineStyle: {
|
|
1147
|
+
type: 'dashed',
|
|
1148
|
+
},
|
|
1149
|
+
}
|
|
1026
1150
|
};
|
|
1151
|
+
const radialAxisOptions = getValueAxisOptions(radiusAxisOverrides);
|
|
1152
|
+
radiusAxis.push(radialAxisOptions);
|
|
1153
|
+
this.result.radiusAxis = radiusAxis;
|
|
1027
1154
|
}
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
* Especialista en visualización de bandas/barras verticales.
|
|
1034
|
-
* Implementa patrones de interacción ZRender y resaltado de grupos.
|
|
1035
|
-
* @see {@link vs-echarts/docs/charts/vertical-bands-patterns.md}
|
|
1036
|
-
*/
|
|
1037
|
-
class EchartsVerticalBandsComponent extends BaseEchartsComponent {
|
|
1038
|
-
builder;
|
|
1039
|
-
constructor() {
|
|
1040
|
-
super();
|
|
1041
|
-
this.builder = new VerticalBandsBuilder();
|
|
1155
|
+
addAngleAxis(data, overrides) {
|
|
1156
|
+
const angleAxis = [];
|
|
1157
|
+
const categoryAxisOptions = this.getCategoryAxisOptions(data, overrides);
|
|
1158
|
+
angleAxis.push(categoryAxisOptions);
|
|
1159
|
+
this.result.angleAxis = angleAxis;
|
|
1042
1160
|
}
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
this.setupAdditionalInteractions();
|
|
1161
|
+
addLegend() {
|
|
1162
|
+
this.result.legend = getLegendOptions();
|
|
1046
1163
|
}
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1164
|
+
// No-ops for ring charts
|
|
1165
|
+
addGraphic() { }
|
|
1166
|
+
getResult() {
|
|
1167
|
+
return this.result;
|
|
1168
|
+
}
|
|
1169
|
+
;
|
|
1170
|
+
/**
|
|
1171
|
+
* Formatea un valor utilizando el callback inyectado.
|
|
1172
|
+
*/
|
|
1173
|
+
formatCellValue(value, key) {
|
|
1174
|
+
return this.valueFormatter(value, key);
|
|
1175
|
+
}
|
|
1176
|
+
// Setters
|
|
1177
|
+
/**
|
|
1178
|
+
* Permite inyectar un formateador de valores externo.
|
|
1179
|
+
*/
|
|
1180
|
+
setValueFormatter(formatter) {
|
|
1181
|
+
if (formatter) {
|
|
1182
|
+
this.valueFormatter = formatter;
|
|
1052
1183
|
}
|
|
1053
|
-
super.onInputChanges(changes);
|
|
1054
1184
|
}
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
const pointInPixel = [params.offsetX, params.offsetY];
|
|
1063
|
-
if (this.chartInstance.containPixel('grid', pointInPixel)) {
|
|
1064
|
-
const xIndexResult = this.chartInstance.convertFromPixel({ xAxisIndex: 0 }, pointInPixel);
|
|
1065
|
-
const xIndex = Array.isArray(xIndexResult) ? xIndexResult[0] : xIndexResult;
|
|
1066
|
-
if (typeof xIndex === 'number' && xIndex >= 0) {
|
|
1067
|
-
this.handleSelection(xIndex, -1); // Use -1 or null to indicate sector selection without specific series
|
|
1068
|
-
}
|
|
1069
|
-
}
|
|
1070
|
-
}
|
|
1071
|
-
});
|
|
1072
|
-
// 2. Mouseover for Group Highlighting
|
|
1073
|
-
this.chartInstance.on('mouseover', (params) => {
|
|
1074
|
-
if (params.dataIndex !== undefined) {
|
|
1075
|
-
this.highlightSector(params.dataIndex);
|
|
1076
|
-
}
|
|
1077
|
-
});
|
|
1078
|
-
this.chartInstance.on('mouseout', () => {
|
|
1079
|
-
this.clearHighlight();
|
|
1080
|
-
});
|
|
1185
|
+
/**
|
|
1186
|
+
* Permite inyectar una paleta de colores básica.
|
|
1187
|
+
*/
|
|
1188
|
+
setPalette(palette) {
|
|
1189
|
+
if (palette) {
|
|
1190
|
+
this.palette = palette;
|
|
1191
|
+
}
|
|
1081
1192
|
}
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
dataIndex: index
|
|
1090
|
-
});
|
|
1193
|
+
/**
|
|
1194
|
+
* Permite inyectar un resolver de colores dinámico.
|
|
1195
|
+
*/
|
|
1196
|
+
setColorResolver(resolver) {
|
|
1197
|
+
if (resolver) {
|
|
1198
|
+
this.colorResolver = resolver;
|
|
1199
|
+
}
|
|
1091
1200
|
}
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1201
|
+
// Utils
|
|
1202
|
+
getCategoryAxisOptions(data, overrides) {
|
|
1203
|
+
const categoryAxisOptionsOverrides = {
|
|
1204
|
+
...overrides.categoryAxis[0],
|
|
1205
|
+
data: data.categories,
|
|
1206
|
+
};
|
|
1207
|
+
const categoryAxisOptions = getCategoryAxisOptions(categoryAxisOptionsOverrides);
|
|
1208
|
+
return categoryAxisOptions;
|
|
1209
|
+
}
|
|
1210
|
+
getValueAxisOptions(data, overrides) {
|
|
1211
|
+
const valueAxisOptions = getValueAxisOptions();
|
|
1212
|
+
return valueAxisOptions;
|
|
1100
1213
|
}
|
|
1214
|
+
}
|
|
1215
|
+
|
|
1216
|
+
class EchartsBarComponent extends BaseEchartsComponent {
|
|
1101
1217
|
/**
|
|
1102
|
-
*
|
|
1218
|
+
* Opciones escenciales inmutables estaticas comunes a todos los charts de barras.
|
|
1103
1219
|
*/
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1220
|
+
baseSeriesOptions = {
|
|
1221
|
+
type: 'bar',
|
|
1222
|
+
barMaxWidth: 50,
|
|
1223
|
+
barGap: '15%',
|
|
1224
|
+
barCategoryGap: '35%',
|
|
1225
|
+
animation: true,
|
|
1226
|
+
animationDuration: 1000,
|
|
1227
|
+
animationEasing: 'cubicOut',
|
|
1228
|
+
itemStyle: {
|
|
1229
|
+
borderRadius: [4, 4, 0, 0],
|
|
1230
|
+
},
|
|
1231
|
+
stack: undefined,
|
|
1232
|
+
emphasis: {
|
|
1233
|
+
focus: 'none'
|
|
1234
|
+
},
|
|
1235
|
+
showBackground: true,
|
|
1236
|
+
backgroundStyle: {
|
|
1237
|
+
color: 'rgba(180, 180, 180, 0.2)' // gris claro
|
|
1238
|
+
},
|
|
1239
|
+
label: {
|
|
1240
|
+
show: false,
|
|
1241
|
+
position: 'top',
|
|
1242
|
+
}
|
|
1243
|
+
};
|
|
1244
|
+
// va a tener que estar en el base como "abstract".
|
|
1245
|
+
baseProduct = {
|
|
1246
|
+
chartKey: 'bar',
|
|
1247
|
+
baseOptions: {
|
|
1248
|
+
series: this.baseSeriesOptions,
|
|
1108
1249
|
}
|
|
1250
|
+
};
|
|
1251
|
+
builder = new EChartBuilder(this.baseProduct);
|
|
1252
|
+
director = new VSECDirector(this.builder);
|
|
1253
|
+
constructor() {
|
|
1254
|
+
super();
|
|
1255
|
+
}
|
|
1256
|
+
// va a tener que estar en el base como "abstract".
|
|
1257
|
+
make(makeOpts) {
|
|
1258
|
+
this.director.makeBar(this.data, this.optionsOverrides, makeOpts);
|
|
1109
1259
|
}
|
|
1110
1260
|
updateChartOptions() {
|
|
1111
1261
|
if (!this.chartInstance)
|
|
1112
1262
|
return;
|
|
1113
1263
|
if (!this.data)
|
|
1114
1264
|
return;
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
this.
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
// 2. Obtenemos las bases del chart usando el builder
|
|
1123
|
-
let baseOptions = this.builder.build(this.data, this.optionsOverrides);
|
|
1124
|
-
// 3. Re-apply legend selection state if exists
|
|
1265
|
+
const makeBarOpts = {
|
|
1266
|
+
valueFormatter: this.valueFormatter,
|
|
1267
|
+
palette: this.palette,
|
|
1268
|
+
colorResolver: this.colorResolver,
|
|
1269
|
+
};
|
|
1270
|
+
this.make(makeBarOpts);
|
|
1271
|
+
const baseOptions = this.builder.getResult();
|
|
1125
1272
|
if (this.currentLegendSelected && baseOptions.legend) {
|
|
1126
1273
|
baseOptions.legend.selected = { ...this.currentLegendSelected };
|
|
1127
1274
|
}
|
|
1128
|
-
// 4. Apply persistent selection style if a sector is selected
|
|
1129
1275
|
if (this.selectedCategoryIndex !== null && baseOptions.series) {
|
|
1130
|
-
const seriesArray = baseOptions.series;
|
|
1131
|
-
baseOptions.series = seriesArray.map((s, sIdx) => {
|
|
1132
|
-
if (s.type === 'bar' && Array.isArray(s.data)) {
|
|
1133
|
-
return {
|
|
1134
|
-
...s,
|
|
1135
|
-
emphasis: {
|
|
1136
|
-
disabled: true
|
|
1137
|
-
},
|
|
1138
|
-
data: s.data.map((val, idx) => {
|
|
1139
|
-
const isSelected = idx === this.selectedCategoryIndex;
|
|
1140
|
-
const isBarSelected = isSelected && sIdx === this.selectedSeriesIndex;
|
|
1141
|
-
const itemVal = (val && typeof val === 'object' && val.value !== undefined) ? val.value : val;
|
|
1142
|
-
return {
|
|
1143
|
-
value: itemVal,
|
|
1144
|
-
itemStyle: {
|
|
1145
|
-
opacity: isSelected ? (isBarSelected ? 1 : 0.5) : 0.15,
|
|
1146
|
-
borderWidth: 0
|
|
1147
|
-
}
|
|
1148
|
-
};
|
|
1149
|
-
})
|
|
1150
|
-
};
|
|
1151
|
-
}
|
|
1152
|
-
return s;
|
|
1153
|
-
});
|
|
1154
|
-
}
|
|
1155
|
-
this.triggerUpdate(baseOptions);
|
|
1156
|
-
}
|
|
1157
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: EchartsVerticalBandsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1158
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.19", type: EchartsVerticalBandsComponent, isStandalone: true, selector: "vs-echarts-vertical-bands", providers: [provideVSEcharts()], usesInheritance: true, ngImport: i0, template: "<div\n class=\"echarts-container\"\n echarts\n [options]=\"chartOptions\"\n [autoResize]=\"true\"\n (chartInit)=\"onChartInit($event)\"\n (chartClick)=\"onChartClick($event)\"\n (legendSelectChanged)=\"onLegendSelectChanged($event)\"\n></div>\n", styles: [".echarts-container{width:100%;height:100%;position:relative}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: NgxEchartsDirective, selector: "echarts, [echarts]", inputs: ["options", "theme", "initOpts", "merge", "autoResize", "loading", "loadingType", "loadingOpts"], outputs: ["chartInit", "optionsError", "chartClick", "chartDblClick", "chartMouseDown", "chartMouseMove", "chartMouseUp", "chartMouseOver", "chartMouseOut", "chartGlobalOut", "chartContextMenu", "chartHighlight", "chartDownplay", "chartSelectChanged", "chartLegendSelectChanged", "chartLegendSelected", "chartLegendUnselected", "chartLegendLegendSelectAll", "chartLegendLegendInverseSelect", "chartLegendScroll", "chartDataZoom", "chartDataRangeSelected", "chartGraphRoam", "chartGeoRoam", "chartTreeRoam", "chartTimelineChanged", "chartTimelinePlayChanged", "chartRestore", "chartDataViewChanged", "chartMagicTypeChanged", "chartGeoSelectChanged", "chartGeoSelected", "chartGeoUnselected", "chartAxisAreaSelected", "chartBrush", "chartBrushEnd", "chartBrushSelected", "chartGlobalCursorTaken", "chartRendered", "chartFinished"], exportAs: ["echarts"] }] });
|
|
1159
|
-
}
|
|
1160
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: EchartsVerticalBandsComponent, decorators: [{
|
|
1161
|
-
type: Component,
|
|
1162
|
-
args: [{ selector: 'vs-echarts-vertical-bands', standalone: true, imports: [
|
|
1163
|
-
CommonModule,
|
|
1164
|
-
NgxEchartsDirective,
|
|
1165
|
-
], providers: [provideVSEcharts()], template: "<div\n class=\"echarts-container\"\n echarts\n [options]=\"chartOptions\"\n [autoResize]=\"true\"\n (chartInit)=\"onChartInit($event)\"\n (chartClick)=\"onChartClick($event)\"\n (legendSelectChanged)=\"onLegendSelectChanged($event)\"\n></div>\n", styles: [".echarts-container{width:100%;height:100%;position:relative}\n"] }]
|
|
1166
|
-
}], ctorParameters: () => [] });
|
|
1167
|
-
|
|
1168
|
-
/**
|
|
1169
|
-
* BarBuilder
|
|
1170
|
-
*
|
|
1171
|
-
* Especializado en construir opciones para gráficos de barras generales.
|
|
1172
|
-
*/
|
|
1173
|
-
class BarBuilder extends BaseEchartBuilder {
|
|
1174
|
-
constructor() {
|
|
1175
|
-
super();
|
|
1176
|
-
}
|
|
1177
|
-
build(data, overrides) {
|
|
1178
|
-
if (!data || !data.series.length)
|
|
1179
|
-
return {};
|
|
1180
|
-
const { itemStyle, emphasis = { focus: 'none' }, stack = undefined, showBackground = false, coordinateSystem = 'cartesian2d', } = overrides.bar.series;
|
|
1181
|
-
const itStBorderRadius = itemStyle?.borderRadius ?? [4, 4, 0, 0];
|
|
1182
|
-
const emphasisFocus = emphasis.focus ?? 'none';
|
|
1183
|
-
const series = data.series.map((s) => {
|
|
1184
|
-
const seriesOption = {
|
|
1185
|
-
name: s.name,
|
|
1186
|
-
type: 'bar',
|
|
1187
|
-
barMaxWidth: 50,
|
|
1188
|
-
barGap: '15%',
|
|
1189
|
-
barCategoryGap: '35%',
|
|
1190
|
-
animation: true,
|
|
1191
|
-
animationDuration: 1000,
|
|
1192
|
-
animationEasing: 'cubicOut',
|
|
1193
|
-
coordinateSystem,
|
|
1194
|
-
itemStyle: {
|
|
1195
|
-
borderRadius: itStBorderRadius,
|
|
1196
|
-
},
|
|
1197
|
-
data: s.data,
|
|
1198
|
-
stack,
|
|
1199
|
-
emphasis: {
|
|
1200
|
-
focus: emphasisFocus
|
|
1201
|
-
},
|
|
1202
|
-
showBackground,
|
|
1203
|
-
backgroundStyle: {
|
|
1204
|
-
color: 'rgba(180, 180, 180, 0.2)' // gris claro
|
|
1205
|
-
},
|
|
1206
|
-
label: {
|
|
1207
|
-
show: false,
|
|
1208
|
-
position: 'top',
|
|
1209
|
-
formatter: (params) => {
|
|
1210
|
-
const key = s.originalKey || (data.categoryKeys ? data.categoryKeys[params.dataIndex] : String(params.dataIndex));
|
|
1211
|
-
return this.formatCellValue(params.value, key);
|
|
1212
|
-
}
|
|
1213
|
-
}
|
|
1214
|
-
};
|
|
1215
|
-
// Inyectar el resolver de color si existe
|
|
1216
|
-
if (this.colorResolver && seriesOption.itemStyle) {
|
|
1217
|
-
seriesOption.itemStyle.color = this.colorResolver;
|
|
1218
|
-
}
|
|
1219
|
-
return seriesOption;
|
|
1220
|
-
});
|
|
1221
|
-
const common = this.getCommonOptions(overrides);
|
|
1222
|
-
const xAxis = [];
|
|
1223
|
-
const yAxis = [];
|
|
1224
|
-
const radiusAxis = [];
|
|
1225
|
-
const polar = [];
|
|
1226
|
-
const angleAxis = [];
|
|
1227
|
-
const categoryAxisOptionsOverrides = {
|
|
1228
|
-
...overrides.axis.categoryAxis[0],
|
|
1229
|
-
data: data.categories,
|
|
1230
|
-
};
|
|
1231
|
-
const categoryAxisOptions = getCategoryAxisOptions(categoryAxisOptionsOverrides);
|
|
1232
|
-
const valueAxisOptions = getValueAxisOptions();
|
|
1233
|
-
if (coordinateSystem == "polar") {
|
|
1234
|
-
// polar coord system.
|
|
1235
|
-
/** estilos exclusivos hardcodeados para el eje de valores del sistema de coordenadas polar*/
|
|
1236
|
-
const radiusAxisOverrides = {
|
|
1237
|
-
axisTick: {
|
|
1238
|
-
show: false,
|
|
1239
|
-
},
|
|
1240
|
-
axisLabel: {
|
|
1241
|
-
margin: 2,
|
|
1242
|
-
fontSize: 8,
|
|
1243
|
-
align: 'right',
|
|
1244
|
-
rotate: 20,
|
|
1245
|
-
verticalAlign: 'top',
|
|
1246
|
-
},
|
|
1247
|
-
axisLine: {
|
|
1248
|
-
lineStyle: {
|
|
1249
|
-
type: 'dashed',
|
|
1250
|
-
},
|
|
1276
|
+
const seriesArray = baseOptions.series;
|
|
1277
|
+
baseOptions.series = seriesArray.map((s, sIdx) => {
|
|
1278
|
+
if (s.type === 'bar' && Array.isArray(s.data)) {
|
|
1279
|
+
return {
|
|
1280
|
+
...s,
|
|
1281
|
+
emphasis: {
|
|
1282
|
+
disabled: true
|
|
1283
|
+
},
|
|
1284
|
+
data: s.data.map((val, idx) => {
|
|
1285
|
+
const isSelected = idx === this.selectedCategoryIndex;
|
|
1286
|
+
const isBarSelected = isSelected && sIdx === this.selectedSeriesIndex;
|
|
1287
|
+
const itemVal = (val && typeof val === 'object' && val.value !== undefined) ? val.value : val;
|
|
1288
|
+
return {
|
|
1289
|
+
value: itemVal,
|
|
1290
|
+
itemStyle: {
|
|
1291
|
+
opacity: isSelected ? (isBarSelected ? 1 : 0.5) : 0.15,
|
|
1292
|
+
borderWidth: 0
|
|
1293
|
+
}
|
|
1294
|
+
};
|
|
1295
|
+
})
|
|
1296
|
+
};
|
|
1251
1297
|
}
|
|
1252
|
-
|
|
1253
|
-
angleAxis.push(categoryAxisOptions);
|
|
1254
|
-
const radialAxisOptions = getValueAxisOptions(radiusAxisOverrides);
|
|
1255
|
-
radiusAxis.push(radialAxisOptions);
|
|
1256
|
-
polar.push({
|
|
1257
|
-
radius: '65%',
|
|
1258
|
-
center: ["50%", "44%"],
|
|
1298
|
+
return s;
|
|
1259
1299
|
});
|
|
1260
1300
|
}
|
|
1261
|
-
|
|
1262
|
-
// cartesian 2d coord system.
|
|
1263
|
-
if (overrides.bar.orientation === 'h') {
|
|
1264
|
-
xAxis.push(valueAxisOptions);
|
|
1265
|
-
yAxis.push(categoryAxisOptions);
|
|
1266
|
-
}
|
|
1267
|
-
else {
|
|
1268
|
-
xAxis.push(categoryAxisOptions);
|
|
1269
|
-
yAxis.push(valueAxisOptions);
|
|
1270
|
-
}
|
|
1271
|
-
}
|
|
1272
|
-
const { trigger = 'item' } = overrides.tooltip;
|
|
1273
|
-
const tooltipOptionsOverrides = {
|
|
1274
|
-
trigger,
|
|
1275
|
-
};
|
|
1276
|
-
return {
|
|
1277
|
-
...common,
|
|
1278
|
-
tooltip: {
|
|
1279
|
-
...getTooltipOptions(tooltipOptionsOverrides),
|
|
1280
|
-
formatter: getTooltipFormatter(trigger, data, this.formatCellValue.bind(this))
|
|
1281
|
-
},
|
|
1282
|
-
legend: getLegendOptions(),
|
|
1283
|
-
xAxis,
|
|
1284
|
-
yAxis,
|
|
1285
|
-
radiusAxis,
|
|
1286
|
-
angleAxis,
|
|
1287
|
-
polar,
|
|
1288
|
-
series: series
|
|
1289
|
-
};
|
|
1290
|
-
}
|
|
1291
|
-
}
|
|
1292
|
-
|
|
1293
|
-
/**
|
|
1294
|
-
* EchartsBarComponent
|
|
1295
|
-
*
|
|
1296
|
-
* Componente especialista para visualización de gráficos de barras.
|
|
1297
|
-
* Implementa patrones de interacción ZRender y resaltado de grupos.
|
|
1298
|
-
*/
|
|
1299
|
-
class EchartsBarComponent extends BaseEchartsComponent {
|
|
1300
|
-
builder;
|
|
1301
|
-
constructor() {
|
|
1302
|
-
super();
|
|
1303
|
-
this.builder = new BarBuilder();
|
|
1301
|
+
this.triggerUpdate(baseOptions);
|
|
1304
1302
|
}
|
|
1305
1303
|
onChartInit(instance) {
|
|
1306
1304
|
super.onChartInit(instance);
|
|
@@ -1357,49 +1355,6 @@ class EchartsBarComponent extends BaseEchartsComponent {
|
|
|
1357
1355
|
this.updateChartOptions();
|
|
1358
1356
|
}
|
|
1359
1357
|
}
|
|
1360
|
-
updateChartOptions() {
|
|
1361
|
-
if (!this.chartInstance)
|
|
1362
|
-
return;
|
|
1363
|
-
if (!this.data)
|
|
1364
|
-
return;
|
|
1365
|
-
if (this.valueFormatter)
|
|
1366
|
-
this.builder.setValueFormatter(this.valueFormatter);
|
|
1367
|
-
if (this.palette)
|
|
1368
|
-
this.builder.setPalette(this.palette);
|
|
1369
|
-
if (this.colorResolver)
|
|
1370
|
-
this.builder.setColorResolver(this.colorResolver);
|
|
1371
|
-
let baseOptions = this.builder.build(this.data, this.optionsOverrides);
|
|
1372
|
-
if (this.currentLegendSelected && baseOptions.legend) {
|
|
1373
|
-
baseOptions.legend.selected = { ...this.currentLegendSelected };
|
|
1374
|
-
}
|
|
1375
|
-
if (this.selectedCategoryIndex !== null && baseOptions.series) {
|
|
1376
|
-
const seriesArray = baseOptions.series;
|
|
1377
|
-
baseOptions.series = seriesArray.map((s, sIdx) => {
|
|
1378
|
-
if (s.type === 'bar' && Array.isArray(s.data)) {
|
|
1379
|
-
return {
|
|
1380
|
-
...s,
|
|
1381
|
-
emphasis: {
|
|
1382
|
-
disabled: true
|
|
1383
|
-
},
|
|
1384
|
-
data: s.data.map((val, idx) => {
|
|
1385
|
-
const isSelected = idx === this.selectedCategoryIndex;
|
|
1386
|
-
const isBarSelected = isSelected && sIdx === this.selectedSeriesIndex;
|
|
1387
|
-
const itemVal = (val && typeof val === 'object' && val.value !== undefined) ? val.value : val;
|
|
1388
|
-
return {
|
|
1389
|
-
value: itemVal,
|
|
1390
|
-
itemStyle: {
|
|
1391
|
-
opacity: isSelected ? (isBarSelected ? 1 : 0.5) : 0.15,
|
|
1392
|
-
borderWidth: 0
|
|
1393
|
-
}
|
|
1394
|
-
};
|
|
1395
|
-
})
|
|
1396
|
-
};
|
|
1397
|
-
}
|
|
1398
|
-
return s;
|
|
1399
|
-
});
|
|
1400
|
-
}
|
|
1401
|
-
this.triggerUpdate(baseOptions);
|
|
1402
|
-
}
|
|
1403
1358
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: EchartsBarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1404
1359
|
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.19", type: EchartsBarComponent, isStandalone: true, selector: "vs-echarts-bar", providers: [provideVSEcharts()], usesInheritance: true, ngImport: i0, template: "<div class=\"echarts-container\" echarts [options]=\"chartOptions\" [autoResize]=\"true\" (chartInit)=\"onChartInit($event)\" (chartClick)=\"onChartClick($event)\" (legendSelectChanged)=\"onLegendSelectChanged($event)\"></div>\n", styles: [".echarts-container{width:100%;height:100%;position:relative}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: NgxEchartsDirective, selector: "echarts, [echarts]", inputs: ["options", "theme", "initOpts", "merge", "autoResize", "loading", "loadingType", "loadingOpts"], outputs: ["chartInit", "optionsError", "chartClick", "chartDblClick", "chartMouseDown", "chartMouseMove", "chartMouseUp", "chartMouseOver", "chartMouseOut", "chartGlobalOut", "chartContextMenu", "chartHighlight", "chartDownplay", "chartSelectChanged", "chartLegendSelectChanged", "chartLegendSelected", "chartLegendUnselected", "chartLegendLegendSelectAll", "chartLegendLegendInverseSelect", "chartLegendScroll", "chartDataZoom", "chartDataRangeSelected", "chartGraphRoam", "chartGeoRoam", "chartTreeRoam", "chartTimelineChanged", "chartTimelinePlayChanged", "chartRestore", "chartDataViewChanged", "chartMagicTypeChanged", "chartGeoSelectChanged", "chartGeoSelected", "chartGeoUnselected", "chartAxisAreaSelected", "chartBrush", "chartBrushEnd", "chartBrushSelected", "chartGlobalCursorTaken", "chartRendered", "chartFinished"], exportAs: ["echarts"] }] });
|
|
1405
1360
|
}
|
|
@@ -1411,86 +1366,258 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImpo
|
|
|
1411
1366
|
], providers: [provideVSEcharts()], template: "<div class=\"echarts-container\" echarts [options]=\"chartOptions\" [autoResize]=\"true\" (chartInit)=\"onChartInit($event)\" (chartClick)=\"onChartClick($event)\" (legendSelectChanged)=\"onLegendSelectChanged($event)\"></div>\n", styles: [".echarts-container{width:100%;height:100%;position:relative}\n"] }]
|
|
1412
1367
|
}], ctorParameters: () => [] });
|
|
1413
1368
|
|
|
1414
|
-
class
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
itemStyle: {
|
|
1434
|
-
shadowColor: 'rgba(0, 0, 0, 0.2)',
|
|
1435
|
-
shadowBlur: 5,
|
|
1436
|
-
shadowOffsetY: 2,
|
|
1437
|
-
},
|
|
1438
|
-
lineStyle: {
|
|
1439
|
-
width: 2,
|
|
1440
|
-
shadowColor: 'rgba(0, 0, 0, 0.2)',
|
|
1441
|
-
shadowBlur: 8,
|
|
1442
|
-
shadowOffsetY: 6,
|
|
1443
|
-
cap: 'round',
|
|
1444
|
-
join: 'round',
|
|
1445
|
-
},
|
|
1446
|
-
emphasis: {
|
|
1447
|
-
focus: 'none',
|
|
1448
|
-
itemStyle: {
|
|
1449
|
-
borderWidth: 2,
|
|
1450
|
-
shadowBlur: 10,
|
|
1451
|
-
},
|
|
1452
|
-
lineStyle: {
|
|
1453
|
-
width: 4,
|
|
1454
|
-
shadowBlur: 12,
|
|
1455
|
-
}
|
|
1456
|
-
},
|
|
1457
|
-
areaStyle,
|
|
1458
|
-
stack,
|
|
1459
|
-
};
|
|
1460
|
-
// Inyectar el resolver de color si existe
|
|
1461
|
-
if (this.colorResolver && seriesOption.itemStyle != undefined) {
|
|
1462
|
-
seriesOption.itemStyle.color = this.colorResolver;
|
|
1463
|
-
}
|
|
1464
|
-
return seriesOption;
|
|
1465
|
-
});
|
|
1466
|
-
const common = this.getCommonOptions(overrides);
|
|
1467
|
-
const categoryAxisOptions = {
|
|
1468
|
-
...overrides.axis.categoryAxis[0],
|
|
1469
|
-
data: data.categories,
|
|
1369
|
+
class EChartsHBarComponent extends EchartsBarComponent {
|
|
1370
|
+
variantSeriesOptionsBase = merge$1(this.baseSeriesOptions, {
|
|
1371
|
+
showBackground: false,
|
|
1372
|
+
itemStyle: {
|
|
1373
|
+
borderRadius: [0, 4, 4, 0],
|
|
1374
|
+
}
|
|
1375
|
+
});
|
|
1376
|
+
variantBaseProduct = {
|
|
1377
|
+
chartKey: 'hBar',
|
|
1378
|
+
baseOptions: {
|
|
1379
|
+
series: this.variantSeriesOptionsBase,
|
|
1380
|
+
}
|
|
1381
|
+
};
|
|
1382
|
+
builder = new EChartBuilder(this.variantBaseProduct);
|
|
1383
|
+
director = new VSECDirector(this.builder);
|
|
1384
|
+
make(makeOpts) {
|
|
1385
|
+
makeOpts.axisTypes = {
|
|
1386
|
+
x: 'value',
|
|
1387
|
+
y: 'category',
|
|
1470
1388
|
};
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1389
|
+
this.director.makeBar(this.data, this.optionsOverrides, makeOpts);
|
|
1390
|
+
}
|
|
1391
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: EChartsHBarComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
1392
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.19", type: EChartsHBarComponent, isStandalone: true, selector: "vs-echarts-bar", providers: [provideVSEcharts()], usesInheritance: true, ngImport: i0, template: "<div class=\"echarts-container\" echarts [options]=\"chartOptions\" [autoResize]=\"true\" (chartInit)=\"onChartInit($event)\" (chartClick)=\"onChartClick($event)\" (legendSelectChanged)=\"onLegendSelectChanged($event)\"></div>\n", styles: [".echarts-container{width:100%;height:100%;position:relative}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: NgxEchartsDirective, selector: "echarts, [echarts]", inputs: ["options", "theme", "initOpts", "merge", "autoResize", "loading", "loadingType", "loadingOpts"], outputs: ["chartInit", "optionsError", "chartClick", "chartDblClick", "chartMouseDown", "chartMouseMove", "chartMouseUp", "chartMouseOver", "chartMouseOut", "chartGlobalOut", "chartContextMenu", "chartHighlight", "chartDownplay", "chartSelectChanged", "chartLegendSelectChanged", "chartLegendSelected", "chartLegendUnselected", "chartLegendLegendSelectAll", "chartLegendLegendInverseSelect", "chartLegendScroll", "chartDataZoom", "chartDataRangeSelected", "chartGraphRoam", "chartGeoRoam", "chartTreeRoam", "chartTimelineChanged", "chartTimelinePlayChanged", "chartRestore", "chartDataViewChanged", "chartMagicTypeChanged", "chartGeoSelectChanged", "chartGeoSelected", "chartGeoUnselected", "chartAxisAreaSelected", "chartBrush", "chartBrushEnd", "chartBrushSelected", "chartGlobalCursorTaken", "chartRendered", "chartFinished"], exportAs: ["echarts"] }] });
|
|
1393
|
+
}
|
|
1394
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: EChartsHBarComponent, decorators: [{
|
|
1395
|
+
type: Component,
|
|
1396
|
+
args: [{ selector: 'vs-echarts-bar', standalone: true, imports: [
|
|
1397
|
+
CommonModule,
|
|
1398
|
+
NgxEchartsDirective,
|
|
1399
|
+
], providers: [provideVSEcharts()], template: "<div class=\"echarts-container\" echarts [options]=\"chartOptions\" [autoResize]=\"true\" (chartInit)=\"onChartInit($event)\" (chartClick)=\"onChartClick($event)\" (legendSelectChanged)=\"onLegendSelectChanged($event)\"></div>\n", styles: [".echarts-container{width:100%;height:100%;position:relative}\n"] }]
|
|
1400
|
+
}] });
|
|
1401
|
+
|
|
1402
|
+
class EChartsBarStackedComponent extends EchartsBarComponent {
|
|
1403
|
+
variantSeriesOptionsBase = merge$1(this.baseSeriesOptions, {
|
|
1404
|
+
showBackground: false,
|
|
1405
|
+
stack: 'total',
|
|
1406
|
+
itemStyle: {
|
|
1407
|
+
borderRadius: [0, 0, 0, 0],
|
|
1408
|
+
},
|
|
1409
|
+
emphasis: {
|
|
1410
|
+
focus: 'series',
|
|
1411
|
+
}
|
|
1412
|
+
});
|
|
1413
|
+
variantBaseProduct = {
|
|
1414
|
+
chartKey: 'barStacked',
|
|
1415
|
+
baseOptions: {
|
|
1416
|
+
series: this.variantSeriesOptionsBase,
|
|
1417
|
+
}
|
|
1418
|
+
};
|
|
1419
|
+
builder = new EChartBuilder(this.variantBaseProduct);
|
|
1420
|
+
director = new VSECDirector(this.builder);
|
|
1421
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: EChartsBarStackedComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
1422
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.19", type: EChartsBarStackedComponent, isStandalone: true, selector: "vs-echarts-bar", providers: [provideVSEcharts()], usesInheritance: true, ngImport: i0, template: "<div class=\"echarts-container\" echarts [options]=\"chartOptions\" [autoResize]=\"true\" (chartInit)=\"onChartInit($event)\" (chartClick)=\"onChartClick($event)\" (legendSelectChanged)=\"onLegendSelectChanged($event)\"></div>\n", styles: [".echarts-container{width:100%;height:100%;position:relative}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: NgxEchartsDirective, selector: "echarts, [echarts]", inputs: ["options", "theme", "initOpts", "merge", "autoResize", "loading", "loadingType", "loadingOpts"], outputs: ["chartInit", "optionsError", "chartClick", "chartDblClick", "chartMouseDown", "chartMouseMove", "chartMouseUp", "chartMouseOver", "chartMouseOut", "chartGlobalOut", "chartContextMenu", "chartHighlight", "chartDownplay", "chartSelectChanged", "chartLegendSelectChanged", "chartLegendSelected", "chartLegendUnselected", "chartLegendLegendSelectAll", "chartLegendLegendInverseSelect", "chartLegendScroll", "chartDataZoom", "chartDataRangeSelected", "chartGraphRoam", "chartGeoRoam", "chartTreeRoam", "chartTimelineChanged", "chartTimelinePlayChanged", "chartRestore", "chartDataViewChanged", "chartMagicTypeChanged", "chartGeoSelectChanged", "chartGeoSelected", "chartGeoUnselected", "chartAxisAreaSelected", "chartBrush", "chartBrushEnd", "chartBrushSelected", "chartGlobalCursorTaken", "chartRendered", "chartFinished"], exportAs: ["echarts"] }] });
|
|
1423
|
+
}
|
|
1424
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: EChartsBarStackedComponent, decorators: [{
|
|
1425
|
+
type: Component,
|
|
1426
|
+
args: [{ selector: 'vs-echarts-bar', standalone: true, imports: [
|
|
1427
|
+
CommonModule,
|
|
1428
|
+
NgxEchartsDirective,
|
|
1429
|
+
], providers: [provideVSEcharts()], template: "<div class=\"echarts-container\" echarts [options]=\"chartOptions\" [autoResize]=\"true\" (chartInit)=\"onChartInit($event)\" (chartClick)=\"onChartClick($event)\" (legendSelectChanged)=\"onLegendSelectChanged($event)\"></div>\n", styles: [".echarts-container{width:100%;height:100%;position:relative}\n"] }]
|
|
1430
|
+
}] });
|
|
1431
|
+
|
|
1432
|
+
class EChartsHBarStackedComponent extends EchartsBarComponent {
|
|
1433
|
+
variantSeriesOptionsBase = merge$1(this.baseSeriesOptions, {
|
|
1434
|
+
showBackground: false,
|
|
1435
|
+
stack: 'total',
|
|
1436
|
+
itemStyle: {
|
|
1437
|
+
borderRadius: [0, 0, 0, 0],
|
|
1438
|
+
},
|
|
1439
|
+
emphasis: {
|
|
1440
|
+
focus: 'series',
|
|
1441
|
+
}
|
|
1442
|
+
});
|
|
1443
|
+
variantBaseProduct = {
|
|
1444
|
+
chartKey: 'hBarStacked',
|
|
1445
|
+
baseOptions: {
|
|
1446
|
+
series: this.variantSeriesOptionsBase,
|
|
1447
|
+
}
|
|
1448
|
+
};
|
|
1449
|
+
builder = new EChartBuilder(this.variantBaseProduct);
|
|
1450
|
+
director = new VSECDirector(this.builder);
|
|
1451
|
+
make(makeOpts) {
|
|
1452
|
+
makeOpts.axisTypes = {
|
|
1453
|
+
x: 'value',
|
|
1454
|
+
y: 'category',
|
|
1474
1455
|
};
|
|
1456
|
+
this.director.makeBar(this.data, this.optionsOverrides, makeOpts);
|
|
1457
|
+
}
|
|
1458
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: EChartsHBarStackedComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
1459
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.19", type: EChartsHBarStackedComponent, isStandalone: true, selector: "vs-echarts-bar", providers: [provideVSEcharts()], usesInheritance: true, ngImport: i0, template: "<div class=\"echarts-container\" echarts [options]=\"chartOptions\" [autoResize]=\"true\" (chartInit)=\"onChartInit($event)\" (chartClick)=\"onChartClick($event)\" (legendSelectChanged)=\"onLegendSelectChanged($event)\"></div>\n", styles: [".echarts-container{width:100%;height:100%;position:relative}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: NgxEchartsDirective, selector: "echarts, [echarts]", inputs: ["options", "theme", "initOpts", "merge", "autoResize", "loading", "loadingType", "loadingOpts"], outputs: ["chartInit", "optionsError", "chartClick", "chartDblClick", "chartMouseDown", "chartMouseMove", "chartMouseUp", "chartMouseOver", "chartMouseOut", "chartGlobalOut", "chartContextMenu", "chartHighlight", "chartDownplay", "chartSelectChanged", "chartLegendSelectChanged", "chartLegendSelected", "chartLegendUnselected", "chartLegendLegendSelectAll", "chartLegendLegendInverseSelect", "chartLegendScroll", "chartDataZoom", "chartDataRangeSelected", "chartGraphRoam", "chartGeoRoam", "chartTreeRoam", "chartTimelineChanged", "chartTimelinePlayChanged", "chartRestore", "chartDataViewChanged", "chartMagicTypeChanged", "chartGeoSelectChanged", "chartGeoSelected", "chartGeoUnselected", "chartAxisAreaSelected", "chartBrush", "chartBrushEnd", "chartBrushSelected", "chartGlobalCursorTaken", "chartRendered", "chartFinished"], exportAs: ["echarts"] }] });
|
|
1460
|
+
}
|
|
1461
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: EChartsHBarStackedComponent, decorators: [{
|
|
1462
|
+
type: Component,
|
|
1463
|
+
args: [{ selector: 'vs-echarts-bar', standalone: true, imports: [
|
|
1464
|
+
CommonModule,
|
|
1465
|
+
NgxEchartsDirective,
|
|
1466
|
+
], providers: [provideVSEcharts()], template: "<div class=\"echarts-container\" echarts [options]=\"chartOptions\" [autoResize]=\"true\" (chartInit)=\"onChartInit($event)\" (chartClick)=\"onChartClick($event)\" (legendSelectChanged)=\"onLegendSelectChanged($event)\"></div>\n", styles: [".echarts-container{width:100%;height:100%;position:relative}\n"] }]
|
|
1467
|
+
}] });
|
|
1468
|
+
|
|
1469
|
+
class EChartsBarStackedRadialComponent extends EchartsBarComponent {
|
|
1470
|
+
variantSeriesOptionsBase = merge$1(this.baseSeriesOptions, {
|
|
1471
|
+
showBackground: false,
|
|
1472
|
+
stack: 'total',
|
|
1473
|
+
itemStyle: {
|
|
1474
|
+
borderRadius: [0, 0, 0, 0],
|
|
1475
|
+
},
|
|
1476
|
+
emphasis: {
|
|
1477
|
+
focus: 'series',
|
|
1478
|
+
},
|
|
1479
|
+
coordinateSystem: 'polar',
|
|
1480
|
+
});
|
|
1481
|
+
variantBaseProduct = {
|
|
1482
|
+
chartKey: 'barStackedRadial',
|
|
1483
|
+
baseOptions: {
|
|
1484
|
+
series: this.variantSeriesOptionsBase,
|
|
1485
|
+
}
|
|
1486
|
+
};
|
|
1487
|
+
builder = new EChartBuilder(this.variantBaseProduct);
|
|
1488
|
+
director = new VSECDirector(this.builder);
|
|
1489
|
+
make(makeOpts) {
|
|
1490
|
+
this.director.makeBarRadial(this.data, this.optionsOverrides, makeOpts);
|
|
1491
|
+
}
|
|
1492
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: EChartsBarStackedRadialComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
1493
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.19", type: EChartsBarStackedRadialComponent, isStandalone: true, selector: "vs-echarts-bar", providers: [provideVSEcharts()], usesInheritance: true, ngImport: i0, template: "<div class=\"echarts-container\" echarts [options]=\"chartOptions\" [autoResize]=\"true\" (chartInit)=\"onChartInit($event)\" (chartClick)=\"onChartClick($event)\" (legendSelectChanged)=\"onLegendSelectChanged($event)\"></div>\n", styles: [".echarts-container{width:100%;height:100%;position:relative}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: NgxEchartsDirective, selector: "echarts, [echarts]", inputs: ["options", "theme", "initOpts", "merge", "autoResize", "loading", "loadingType", "loadingOpts"], outputs: ["chartInit", "optionsError", "chartClick", "chartDblClick", "chartMouseDown", "chartMouseMove", "chartMouseUp", "chartMouseOver", "chartMouseOut", "chartGlobalOut", "chartContextMenu", "chartHighlight", "chartDownplay", "chartSelectChanged", "chartLegendSelectChanged", "chartLegendSelected", "chartLegendUnselected", "chartLegendLegendSelectAll", "chartLegendLegendInverseSelect", "chartLegendScroll", "chartDataZoom", "chartDataRangeSelected", "chartGraphRoam", "chartGeoRoam", "chartTreeRoam", "chartTimelineChanged", "chartTimelinePlayChanged", "chartRestore", "chartDataViewChanged", "chartMagicTypeChanged", "chartGeoSelectChanged", "chartGeoSelected", "chartGeoUnselected", "chartAxisAreaSelected", "chartBrush", "chartBrushEnd", "chartBrushSelected", "chartGlobalCursorTaken", "chartRendered", "chartFinished"], exportAs: ["echarts"] }] });
|
|
1494
|
+
}
|
|
1495
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: EChartsBarStackedRadialComponent, decorators: [{
|
|
1496
|
+
type: Component,
|
|
1497
|
+
args: [{ selector: 'vs-echarts-bar', standalone: true, imports: [
|
|
1498
|
+
CommonModule,
|
|
1499
|
+
NgxEchartsDirective,
|
|
1500
|
+
], providers: [provideVSEcharts()], template: "<div class=\"echarts-container\" echarts [options]=\"chartOptions\" [autoResize]=\"true\" (chartInit)=\"onChartInit($event)\" (chartClick)=\"onChartClick($event)\" (legendSelectChanged)=\"onLegendSelectChanged($event)\"></div>\n", styles: [".echarts-container{width:100%;height:100%;position:relative}\n"] }]
|
|
1501
|
+
}] });
|
|
1502
|
+
|
|
1503
|
+
/**
|
|
1504
|
+
* Applies a visual selection effect to line-based series.
|
|
1505
|
+
* Highlights the selected series and point, and dims everything else.
|
|
1506
|
+
*
|
|
1507
|
+
* @param series The series array to modify
|
|
1508
|
+
* @param selectedCategoryIndex Index of the selected category
|
|
1509
|
+
* @param selectedSeriesIndex Index of the selected series
|
|
1510
|
+
* @returns Modified series array
|
|
1511
|
+
*/
|
|
1512
|
+
function applyLineSelectionStyle(series, selectedCategoryIndex, selectedSeriesIndex) {
|
|
1513
|
+
if (selectedCategoryIndex === null || !series)
|
|
1514
|
+
return series;
|
|
1515
|
+
return series.map((s, sIdx) => {
|
|
1516
|
+
const isSelectedSeries = sIdx === selectedSeriesIndex;
|
|
1517
|
+
// Serie seleccionada: Línea con opacidad 1 para que destaque la tendencia.
|
|
1518
|
+
// Serie NO seleccionada: Opacidad 0.20 para atenuar fuertemente.
|
|
1519
|
+
const seriesOpacity = isSelectedSeries ? 1 : 0.20;
|
|
1475
1520
|
return {
|
|
1476
|
-
...
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1521
|
+
...s,
|
|
1522
|
+
emphasis: {
|
|
1523
|
+
disabled: true // Deshabilitar el énfasis (hover) cuando hay una selección activa
|
|
1524
|
+
},
|
|
1525
|
+
itemStyle: {
|
|
1526
|
+
...s.itemStyle,
|
|
1527
|
+
opacity: seriesOpacity
|
|
1528
|
+
},
|
|
1529
|
+
lineStyle: {
|
|
1530
|
+
...s.lineStyle,
|
|
1531
|
+
opacity: seriesOpacity
|
|
1480
1532
|
},
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1533
|
+
...(s.areaStyle ? {
|
|
1534
|
+
areaStyle: {
|
|
1535
|
+
...s.areaStyle,
|
|
1536
|
+
opacity: isSelectedSeries ? 0.6 : 0.1
|
|
1537
|
+
}
|
|
1538
|
+
} : {}),
|
|
1539
|
+
// Personalizamos los puntos individualmente
|
|
1540
|
+
data: (s.data || []).map((val, idx) => {
|
|
1541
|
+
const isSelectedPoint = isSelectedSeries && idx === selectedCategoryIndex;
|
|
1542
|
+
const isOtherPointInSelectedSeries = isSelectedSeries && idx !== selectedCategoryIndex;
|
|
1543
|
+
const originalPoint = (val && typeof val === 'object') ? val : { value: val };
|
|
1544
|
+
if (isSelectedPoint) {
|
|
1545
|
+
return {
|
|
1546
|
+
...originalPoint,
|
|
1547
|
+
z: 10, // Asegurar que el punto seleccionado esté por encima de los demás
|
|
1548
|
+
itemStyle: {
|
|
1549
|
+
...originalPoint.itemStyle,
|
|
1550
|
+
opacity: 1,
|
|
1551
|
+
borderWidth: 2,
|
|
1552
|
+
borderColor: '#fff',
|
|
1553
|
+
shadowBlur: 10,
|
|
1554
|
+
shadowColor: 'rgba(0,0,0,0.5)'
|
|
1555
|
+
},
|
|
1556
|
+
symbolSize: 12
|
|
1557
|
+
};
|
|
1558
|
+
}
|
|
1559
|
+
else if (isOtherPointInSelectedSeries) {
|
|
1560
|
+
// Puntos de la serie seleccionada que NO son el clicado: un poco más pequeños y traslúcidos
|
|
1561
|
+
return {
|
|
1562
|
+
...originalPoint,
|
|
1563
|
+
itemStyle: {
|
|
1564
|
+
...originalPoint.itemStyle,
|
|
1565
|
+
opacity: 0.5
|
|
1566
|
+
},
|
|
1567
|
+
symbolSize: 6
|
|
1568
|
+
};
|
|
1569
|
+
}
|
|
1570
|
+
// Puntos de otras series o por defecto
|
|
1571
|
+
return val;
|
|
1572
|
+
})
|
|
1485
1573
|
};
|
|
1486
|
-
}
|
|
1574
|
+
});
|
|
1487
1575
|
}
|
|
1488
1576
|
|
|
1489
1577
|
class EchartsLineComponent extends BaseEchartsComponent {
|
|
1490
|
-
|
|
1578
|
+
baseSeriesOptions = {
|
|
1579
|
+
type: 'line',
|
|
1580
|
+
animation: true,
|
|
1581
|
+
animationDuration: 1000,
|
|
1582
|
+
animationEasing: 'cubicOut',
|
|
1583
|
+
smooth: true,
|
|
1584
|
+
smoothMonotone: 'x',
|
|
1585
|
+
symbolSize: 6,
|
|
1586
|
+
itemStyle: {
|
|
1587
|
+
shadowColor: 'rgba(0, 0, 0, 0.2)',
|
|
1588
|
+
shadowBlur: 5,
|
|
1589
|
+
shadowOffsetY: 2,
|
|
1590
|
+
},
|
|
1591
|
+
lineStyle: {
|
|
1592
|
+
width: 2,
|
|
1593
|
+
shadowColor: 'rgba(0, 0, 0, 0.2)',
|
|
1594
|
+
shadowBlur: 8,
|
|
1595
|
+
shadowOffsetY: 6,
|
|
1596
|
+
cap: 'round',
|
|
1597
|
+
join: 'round',
|
|
1598
|
+
},
|
|
1599
|
+
emphasis: {
|
|
1600
|
+
focus: 'none',
|
|
1601
|
+
itemStyle: {
|
|
1602
|
+
borderWidth: 2,
|
|
1603
|
+
shadowBlur: 10,
|
|
1604
|
+
},
|
|
1605
|
+
lineStyle: {
|
|
1606
|
+
width: 4,
|
|
1607
|
+
shadowBlur: 12,
|
|
1608
|
+
}
|
|
1609
|
+
},
|
|
1610
|
+
};
|
|
1611
|
+
baseProduct = {
|
|
1612
|
+
chartKey: 'line',
|
|
1613
|
+
baseOptions: {
|
|
1614
|
+
series: this.baseSeriesOptions,
|
|
1615
|
+
}
|
|
1616
|
+
};
|
|
1617
|
+
builder = new EChartBuilder(this.baseProduct);
|
|
1618
|
+
director = new VSECDirector(this.builder);
|
|
1491
1619
|
constructor() {
|
|
1492
1620
|
super();
|
|
1493
|
-
this.builder = new LineBuilder();
|
|
1494
1621
|
}
|
|
1495
1622
|
onInputChanges(changes) {
|
|
1496
1623
|
if (changes['data']) {
|
|
@@ -1500,41 +1627,96 @@ class EchartsLineComponent extends BaseEchartsComponent {
|
|
|
1500
1627
|
}
|
|
1501
1628
|
super.onInputChanges(changes);
|
|
1502
1629
|
}
|
|
1630
|
+
make(makeOpts) {
|
|
1631
|
+
this.director.makeLine(this.data, this.optionsOverrides, makeOpts);
|
|
1632
|
+
}
|
|
1503
1633
|
updateChartOptions() {
|
|
1504
1634
|
if (!this.chartInstance)
|
|
1505
1635
|
return;
|
|
1506
1636
|
if (!this.data)
|
|
1507
1637
|
return;
|
|
1508
|
-
// 1.
|
|
1509
|
-
|
|
1510
|
-
this.
|
|
1511
|
-
|
|
1512
|
-
this.
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
// 3. Re-apply legend selection state if exists
|
|
1638
|
+
// 1.
|
|
1639
|
+
const makeBarOpts = {
|
|
1640
|
+
valueFormatter: this.valueFormatter,
|
|
1641
|
+
palette: this.palette,
|
|
1642
|
+
colorResolver: this.colorResolver,
|
|
1643
|
+
};
|
|
1644
|
+
this.make(makeBarOpts);
|
|
1645
|
+
const baseOptions = this.builder.getResult();
|
|
1646
|
+
// 2. Re-apply legend selection state if exists
|
|
1518
1647
|
if (this.currentLegendSelected && baseOptions.legend) {
|
|
1519
1648
|
baseOptions.legend.selected = { ...this.currentLegendSelected };
|
|
1520
1649
|
}
|
|
1521
|
-
//
|
|
1650
|
+
//3. Apply persistent selection style if a point is selected
|
|
1522
1651
|
if (this.selectedCategoryIndex !== null && baseOptions.series) {
|
|
1523
1652
|
baseOptions.series = applyLineSelectionStyle(baseOptions.series, this.selectedCategoryIndex, this.selectedSeriesIndex);
|
|
1524
1653
|
}
|
|
1525
1654
|
this.triggerUpdate(baseOptions);
|
|
1526
1655
|
}
|
|
1527
1656
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: EchartsLineComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1528
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.19", type: EchartsLineComponent, isStandalone: true, selector: "vs-echarts-line", providers: [
|
|
1657
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.19", type: EchartsLineComponent, isStandalone: true, selector: "vs-echarts-line", providers: [
|
|
1658
|
+
provideVSEcharts(),
|
|
1659
|
+
], usesInheritance: true, ngImport: i0, template: "<div\n class=\"echarts-container\"\n echarts\n [options]=\"chartOptions\"\n [autoResize]=\"true\"\n (chartInit)=\"onChartInit($event)\"\n (chartClick)=\"onChartClick($event)\"\n (legendSelectChanged)=\"onLegendSelectChanged($event)\"\n></div>", styles: [".echarts-container{width:100%;height:100%;position:relative}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: NgxEchartsDirective, selector: "echarts, [echarts]", inputs: ["options", "theme", "initOpts", "merge", "autoResize", "loading", "loadingType", "loadingOpts"], outputs: ["chartInit", "optionsError", "chartClick", "chartDblClick", "chartMouseDown", "chartMouseMove", "chartMouseUp", "chartMouseOver", "chartMouseOut", "chartGlobalOut", "chartContextMenu", "chartHighlight", "chartDownplay", "chartSelectChanged", "chartLegendSelectChanged", "chartLegendSelected", "chartLegendUnselected", "chartLegendLegendSelectAll", "chartLegendLegendInverseSelect", "chartLegendScroll", "chartDataZoom", "chartDataRangeSelected", "chartGraphRoam", "chartGeoRoam", "chartTreeRoam", "chartTimelineChanged", "chartTimelinePlayChanged", "chartRestore", "chartDataViewChanged", "chartMagicTypeChanged", "chartGeoSelectChanged", "chartGeoSelected", "chartGeoUnselected", "chartAxisAreaSelected", "chartBrush", "chartBrushEnd", "chartBrushSelected", "chartGlobalCursorTaken", "chartRendered", "chartFinished"], exportAs: ["echarts"] }] });
|
|
1529
1660
|
}
|
|
1530
1661
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: EchartsLineComponent, decorators: [{
|
|
1531
1662
|
type: Component,
|
|
1532
1663
|
args: [{ selector: 'vs-echarts-line', standalone: true, imports: [
|
|
1533
1664
|
CommonModule,
|
|
1534
1665
|
NgxEchartsDirective,
|
|
1535
|
-
], providers: [
|
|
1666
|
+
], providers: [
|
|
1667
|
+
provideVSEcharts(),
|
|
1668
|
+
], template: "<div\n class=\"echarts-container\"\n echarts\n [options]=\"chartOptions\"\n [autoResize]=\"true\"\n (chartInit)=\"onChartInit($event)\"\n (chartClick)=\"onChartClick($event)\"\n (legendSelectChanged)=\"onLegendSelectChanged($event)\"\n></div>", styles: [".echarts-container{width:100%;height:100%;position:relative}\n"] }]
|
|
1536
1669
|
}], ctorParameters: () => [] });
|
|
1537
1670
|
|
|
1671
|
+
class EChartsAreaComponent extends EchartsLineComponent {
|
|
1672
|
+
variantSeriesOptionsBase = merge$1(this.baseSeriesOptions, {
|
|
1673
|
+
smooth: true,
|
|
1674
|
+
areaStyle: {},
|
|
1675
|
+
});
|
|
1676
|
+
variantBaseProduct = {
|
|
1677
|
+
chartKey: 'area',
|
|
1678
|
+
baseOptions: {
|
|
1679
|
+
series: this.variantSeriesOptionsBase,
|
|
1680
|
+
}
|
|
1681
|
+
};
|
|
1682
|
+
builder = new EChartBuilder(this.variantBaseProduct);
|
|
1683
|
+
director = new VSECDirector(this.builder);
|
|
1684
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: EChartsAreaComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
1685
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.19", type: EChartsAreaComponent, isStandalone: true, selector: "vs-echarts-bar", providers: [provideVSEcharts()], usesInheritance: true, ngImport: i0, template: "<div\n class=\"echarts-container\"\n echarts\n [options]=\"chartOptions\"\n [autoResize]=\"true\"\n (chartInit)=\"onChartInit($event)\"\n (chartClick)=\"onChartClick($event)\"\n (legendSelectChanged)=\"onLegendSelectChanged($event)\"\n></div>", styles: [".echarts-container{width:100%;height:100%;position:relative}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: NgxEchartsDirective, selector: "echarts, [echarts]", inputs: ["options", "theme", "initOpts", "merge", "autoResize", "loading", "loadingType", "loadingOpts"], outputs: ["chartInit", "optionsError", "chartClick", "chartDblClick", "chartMouseDown", "chartMouseMove", "chartMouseUp", "chartMouseOver", "chartMouseOut", "chartGlobalOut", "chartContextMenu", "chartHighlight", "chartDownplay", "chartSelectChanged", "chartLegendSelectChanged", "chartLegendSelected", "chartLegendUnselected", "chartLegendLegendSelectAll", "chartLegendLegendInverseSelect", "chartLegendScroll", "chartDataZoom", "chartDataRangeSelected", "chartGraphRoam", "chartGeoRoam", "chartTreeRoam", "chartTimelineChanged", "chartTimelinePlayChanged", "chartRestore", "chartDataViewChanged", "chartMagicTypeChanged", "chartGeoSelectChanged", "chartGeoSelected", "chartGeoUnselected", "chartAxisAreaSelected", "chartBrush", "chartBrushEnd", "chartBrushSelected", "chartGlobalCursorTaken", "chartRendered", "chartFinished"], exportAs: ["echarts"] }] });
|
|
1686
|
+
}
|
|
1687
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: EChartsAreaComponent, decorators: [{
|
|
1688
|
+
type: Component,
|
|
1689
|
+
args: [{ selector: 'vs-echarts-bar', standalone: true, imports: [
|
|
1690
|
+
CommonModule,
|
|
1691
|
+
NgxEchartsDirective,
|
|
1692
|
+
], providers: [provideVSEcharts()], template: "<div\n class=\"echarts-container\"\n echarts\n [options]=\"chartOptions\"\n [autoResize]=\"true\"\n (chartInit)=\"onChartInit($event)\"\n (chartClick)=\"onChartClick($event)\"\n (legendSelectChanged)=\"onLegendSelectChanged($event)\"\n></div>", styles: [".echarts-container{width:100%;height:100%;position:relative}\n"] }]
|
|
1693
|
+
}] });
|
|
1694
|
+
|
|
1695
|
+
class EChartsAreaStackComponent extends EchartsLineComponent {
|
|
1696
|
+
variantSeriesOptionsBase = merge$1(this.baseSeriesOptions, {
|
|
1697
|
+
smooth: true,
|
|
1698
|
+
areaStyle: {},
|
|
1699
|
+
stack: 'total',
|
|
1700
|
+
});
|
|
1701
|
+
variantBaseProduct = {
|
|
1702
|
+
chartKey: 'areaStack',
|
|
1703
|
+
baseOptions: {
|
|
1704
|
+
series: this.variantSeriesOptionsBase,
|
|
1705
|
+
}
|
|
1706
|
+
};
|
|
1707
|
+
builder = new EChartBuilder(this.variantBaseProduct);
|
|
1708
|
+
director = new VSECDirector(this.builder);
|
|
1709
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: EChartsAreaStackComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
1710
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.19", type: EChartsAreaStackComponent, isStandalone: true, selector: "vs-echarts-bar", providers: [provideVSEcharts()], usesInheritance: true, ngImport: i0, template: "<div\n class=\"echarts-container\"\n echarts\n [options]=\"chartOptions\"\n [autoResize]=\"true\"\n (chartInit)=\"onChartInit($event)\"\n (chartClick)=\"onChartClick($event)\"\n (legendSelectChanged)=\"onLegendSelectChanged($event)\"\n></div>", styles: [".echarts-container{width:100%;height:100%;position:relative}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: NgxEchartsDirective, selector: "echarts, [echarts]", inputs: ["options", "theme", "initOpts", "merge", "autoResize", "loading", "loadingType", "loadingOpts"], outputs: ["chartInit", "optionsError", "chartClick", "chartDblClick", "chartMouseDown", "chartMouseMove", "chartMouseUp", "chartMouseOver", "chartMouseOut", "chartGlobalOut", "chartContextMenu", "chartHighlight", "chartDownplay", "chartSelectChanged", "chartLegendSelectChanged", "chartLegendSelected", "chartLegendUnselected", "chartLegendLegendSelectAll", "chartLegendLegendInverseSelect", "chartLegendScroll", "chartDataZoom", "chartDataRangeSelected", "chartGraphRoam", "chartGeoRoam", "chartTreeRoam", "chartTimelineChanged", "chartTimelinePlayChanged", "chartRestore", "chartDataViewChanged", "chartMagicTypeChanged", "chartGeoSelectChanged", "chartGeoSelected", "chartGeoUnselected", "chartAxisAreaSelected", "chartBrush", "chartBrushEnd", "chartBrushSelected", "chartGlobalCursorTaken", "chartRendered", "chartFinished"], exportAs: ["echarts"] }] });
|
|
1711
|
+
}
|
|
1712
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: EChartsAreaStackComponent, decorators: [{
|
|
1713
|
+
type: Component,
|
|
1714
|
+
args: [{ selector: 'vs-echarts-bar', standalone: true, imports: [
|
|
1715
|
+
CommonModule,
|
|
1716
|
+
NgxEchartsDirective,
|
|
1717
|
+
], providers: [provideVSEcharts()], template: "<div\n class=\"echarts-container\"\n echarts\n [options]=\"chartOptions\"\n [autoResize]=\"true\"\n (chartInit)=\"onChartInit($event)\"\n (chartClick)=\"onChartClick($event)\"\n (legendSelectChanged)=\"onLegendSelectChanged($event)\"\n></div>", styles: [".echarts-container{width:100%;height:100%;position:relative}\n"] }]
|
|
1718
|
+
}] });
|
|
1719
|
+
|
|
1538
1720
|
// Interfaces de Inputs de Base EChart Component //
|
|
1539
1721
|
|
|
1540
1722
|
;
|
|
@@ -1549,5 +1731,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImpo
|
|
|
1549
1731
|
* Generated bundle index. Do not edit.
|
|
1550
1732
|
*/
|
|
1551
1733
|
|
|
1552
|
-
export { BaseEchartsComponent, EchartsBarComponent, EchartsLineComponent, EchartsRingComponent,
|
|
1734
|
+
export { BaseEchartsComponent, EChartsAreaComponent, EChartsAreaStackComponent, EChartsBarStackedComponent, EChartsBarStackedRadialComponent, EChartsHBarComponent, EChartsHBarStackedComponent, EchartsBarComponent, EchartsLineComponent, EchartsRingComponent, defaultOptionsOverrides, initializeEcharts, provideVSEcharts };
|
|
1553
1735
|
//# sourceMappingURL=visionaris-bruno-vs-echarts.mjs.map
|