@visionaris-bruno/vs-echarts 5.9.1 → 6.0.0
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 +1 -8
- package/fesm2022/visionaris-bruno-vs-echarts.mjs +1114 -930
- package/fesm2022/visionaris-bruno-vs-echarts.mjs.map +1 -1
- package/index.d.ts +286 -151
- 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
|
|
@@ -360,80 +82,47 @@ function defaultOptionsOverrides() {
|
|
|
360
82
|
valueAxis: [],
|
|
361
83
|
},
|
|
362
84
|
line: {
|
|
363
|
-
series: {
|
|
85
|
+
series: {
|
|
86
|
+
smooth: true,
|
|
87
|
+
},
|
|
364
88
|
},
|
|
365
89
|
area: {
|
|
366
90
|
series: {
|
|
367
91
|
smooth: true,
|
|
368
|
-
areaStyle: {},
|
|
369
92
|
},
|
|
370
93
|
},
|
|
371
94
|
areaStack: {
|
|
372
95
|
series: {
|
|
373
96
|
smooth: true,
|
|
374
|
-
areaStyle: {},
|
|
375
|
-
stack: 'total',
|
|
376
97
|
},
|
|
377
98
|
},
|
|
378
99
|
bar: {
|
|
379
|
-
// tooltip: {},
|
|
380
100
|
series: {
|
|
381
101
|
showBackground: true,
|
|
382
102
|
},
|
|
383
103
|
},
|
|
384
104
|
barStacked: {
|
|
385
|
-
// tooltip: {
|
|
386
|
-
// trigger: 'axis',
|
|
387
|
-
// },
|
|
388
105
|
series: {
|
|
389
106
|
showBackground: false,
|
|
390
|
-
stack: 'total',
|
|
391
|
-
itemStyle: {
|
|
392
|
-
borderRadius: [0, 0, 0, 0],
|
|
393
|
-
},
|
|
394
|
-
emphasis: {
|
|
395
|
-
focus: 'series',
|
|
396
|
-
}
|
|
397
107
|
}
|
|
398
108
|
},
|
|
399
109
|
barStackedRadial: {
|
|
400
110
|
series: {
|
|
401
111
|
showBackground: false,
|
|
402
|
-
stack: 'total',
|
|
403
|
-
itemStyle: {
|
|
404
|
-
borderRadius: [0, 0, 0, 0],
|
|
405
|
-
},
|
|
406
|
-
emphasis: {
|
|
407
|
-
focus: 'series',
|
|
408
|
-
},
|
|
409
|
-
coordinateSystem: 'polar',
|
|
410
112
|
}
|
|
411
113
|
},
|
|
412
114
|
hBar: {
|
|
413
|
-
orientation: 'h',
|
|
414
|
-
// tooltip: {},
|
|
415
115
|
series: {
|
|
416
116
|
showBackground: true,
|
|
417
|
-
itemStyle: {
|
|
418
|
-
borderRadius: [0, 4, 4, 0],
|
|
419
|
-
}
|
|
420
117
|
}
|
|
421
118
|
},
|
|
422
119
|
hBarStacked: {
|
|
423
|
-
orientation: 'h',
|
|
424
|
-
// tooltip: {
|
|
425
|
-
// trigger: 'axis',
|
|
426
|
-
// },
|
|
427
120
|
series: {
|
|
428
|
-
stack: 'total',
|
|
429
121
|
showBackground: false,
|
|
430
|
-
itemStyle: {
|
|
431
|
-
borderRadius: [0, 0, 0, 0],
|
|
432
|
-
},
|
|
433
|
-
emphasis: {
|
|
434
|
-
focus: 'series',
|
|
435
|
-
}
|
|
436
122
|
}
|
|
123
|
+
},
|
|
124
|
+
ring: {
|
|
125
|
+
series: {}
|
|
437
126
|
}
|
|
438
127
|
};
|
|
439
128
|
}
|
|
@@ -458,21 +147,21 @@ class BaseEchartsComponent {
|
|
|
458
147
|
/** Formateador de valores para etiquetas y tooltips */
|
|
459
148
|
valueFormatter;
|
|
460
149
|
chartClick = new EventEmitter();
|
|
461
|
-
/** Opciones configuradas para ngx-echarts */
|
|
462
|
-
chartOptions = {};
|
|
463
150
|
/** Subject para debouncing de actualizaciones. ReplaySubject asegura no perder el primer renderizado. */
|
|
464
151
|
updateSubject = new ReplaySubject(1);
|
|
465
152
|
updateSubscription;
|
|
466
|
-
constructor() {
|
|
467
|
-
this.updateSubscription = this.updateSubject.pipe(debounceTime(150)).subscribe(options => {
|
|
468
|
-
this.updateOptions(options);
|
|
469
|
-
});
|
|
470
|
-
}
|
|
471
153
|
chartInstance;
|
|
472
154
|
currentLegendSelected = null;
|
|
473
155
|
/** Estado de selección para filtros cruzados */
|
|
474
156
|
selectedCategoryIndex = null;
|
|
475
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
|
+
}
|
|
476
165
|
ngOnChanges(changes) {
|
|
477
166
|
this.onInputChanges(changes);
|
|
478
167
|
}
|
|
@@ -581,124 +270,371 @@ class BaseEchartsComponent {
|
|
|
581
270
|
triggerUpdate(options) {
|
|
582
271
|
this.updateSubject.next(options);
|
|
583
272
|
}
|
|
584
|
-
/**
|
|
585
|
-
* Método público para forzar el redimensionado desde el padre
|
|
586
|
-
*/
|
|
587
|
-
resize() {
|
|
588
|
-
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;
|
|
589
445
|
}
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
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;
|
|
594
608
|
}
|
|
595
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: BaseEchartsComponent, decorators: [{
|
|
596
|
-
type: Directive,
|
|
597
|
-
args: [{
|
|
598
|
-
standalone: true
|
|
599
|
-
}]
|
|
600
|
-
}], ctorParameters: () => [], propDecorators: { chartContainer: [{
|
|
601
|
-
type: ViewChild,
|
|
602
|
-
args: ['chartContainer', { static: true }]
|
|
603
|
-
}], data: [{
|
|
604
|
-
type: Input
|
|
605
|
-
}], optionsOverrides: [{
|
|
606
|
-
type: Input,
|
|
607
|
-
args: [{
|
|
608
|
-
"transform": (values) => {
|
|
609
|
-
return merge(defaultOptionsOverrides(), values || {});
|
|
610
|
-
}
|
|
611
|
-
}]
|
|
612
|
-
}], palette: [{
|
|
613
|
-
type: Input
|
|
614
|
-
}], colorResolver: [{
|
|
615
|
-
type: Input
|
|
616
|
-
}], valueFormatter: [{
|
|
617
|
-
type: Input
|
|
618
|
-
}], chartClick: [{
|
|
619
|
-
type: Output
|
|
620
|
-
}] } });
|
|
621
609
|
|
|
622
610
|
/**
|
|
623
|
-
*
|
|
611
|
+
* RingBuilder
|
|
624
612
|
*
|
|
625
|
-
*
|
|
626
|
-
* Implementa lógica compartida de paletas y opciones comunes.
|
|
613
|
+
* Builder concreto para el grafico de Ring.
|
|
627
614
|
*
|
|
628
|
-
* @see {@link vs-echarts/docs/internal-architecture.md}
|
|
629
615
|
*/
|
|
630
|
-
class
|
|
616
|
+
class RingBuilder {
|
|
617
|
+
product;
|
|
631
618
|
valueFormatter = (value) => value.toLocaleString();
|
|
632
619
|
palette = [];
|
|
633
|
-
// TODO: Hay que implementar un valor por defecto.
|
|
634
620
|
colorResolver;
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
*/
|
|
639
|
-
setValueFormatter(formatter) {
|
|
640
|
-
if (formatter) {
|
|
641
|
-
this.valueFormatter = formatter;
|
|
642
|
-
}
|
|
643
|
-
}
|
|
644
|
-
/**
|
|
645
|
-
* Permite inyectar una paleta de colores básica.
|
|
646
|
-
*/
|
|
647
|
-
setPalette(palette) {
|
|
648
|
-
if (palette) {
|
|
649
|
-
this.palette = palette;
|
|
650
|
-
}
|
|
621
|
+
result = {};
|
|
622
|
+
constructor(product) {
|
|
623
|
+
this.product = product;
|
|
651
624
|
}
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
*/
|
|
655
|
-
setColorResolver(resolver) {
|
|
656
|
-
if (resolver) {
|
|
657
|
-
this.colorResolver = resolver;
|
|
658
|
-
}
|
|
625
|
+
reset() {
|
|
626
|
+
this.result = {};
|
|
659
627
|
}
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
* TODO: particionar en configuraciones concretas con sus
|
|
664
|
-
* respectivos overrides.
|
|
665
|
-
*/
|
|
666
|
-
getCommonOptions(overrides) {
|
|
667
|
-
const common = {
|
|
668
|
-
backgroundColor: 'transparent',
|
|
669
|
-
textStyle: {
|
|
670
|
-
fontFamily: "'Inter', 'Roboto', 'Open Sans', sans-serif"
|
|
671
|
-
},
|
|
672
|
-
grid: {
|
|
673
|
-
left: '3%',
|
|
674
|
-
right: '4%',
|
|
675
|
-
bottom: '15%',
|
|
676
|
-
top: '20px',
|
|
677
|
-
containLabel: true
|
|
678
|
-
}
|
|
628
|
+
addCommons() {
|
|
629
|
+
const opts = {
|
|
630
|
+
palette: this.palette,
|
|
679
631
|
};
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
return common;
|
|
683
|
-
}
|
|
684
|
-
/**
|
|
685
|
-
* Formatea un valor utilizando el callback inyectado.
|
|
686
|
-
*/
|
|
687
|
-
formatCellValue(value, key) {
|
|
688
|
-
return this.valueFormatter(value, key);
|
|
632
|
+
const common = getCommons(opts);
|
|
633
|
+
merge(this.result, common);
|
|
689
634
|
}
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
/**
|
|
693
|
-
* RingBuilder
|
|
694
|
-
*
|
|
695
|
-
* Especializado en construir opciones para gráficos de tipo Ring (Donas concéntricas).
|
|
696
|
-
* @see {@link vs-echarts/docs/charts/ring-patterns.md}
|
|
697
|
-
*/
|
|
698
|
-
class RingBuilder extends BaseEchartBuilder {
|
|
699
|
-
build(data, overrides) {
|
|
635
|
+
addSeries(data, overrides) {
|
|
700
636
|
if (!data || !data.series.length)
|
|
701
|
-
return
|
|
637
|
+
return;
|
|
702
638
|
const totalRings = data.series.length; // Cada serie es un anillo
|
|
703
639
|
// Configuración dinámica de radios y márgenes
|
|
704
640
|
const margin = totalRings > 1 ? Math.max(0.5, 2.5 - (totalRings * 0.1)) : 0;
|
|
@@ -716,81 +652,194 @@ class RingBuilder extends BaseEchartBuilder {
|
|
|
716
652
|
value: s.data[catIndex],
|
|
717
653
|
originalMeassureKey: s.originalKey || (data.categoryKeys ? data.categoryKeys[catIndex] : '')
|
|
718
654
|
}));
|
|
719
|
-
const
|
|
655
|
+
const dynamicRingSeriesOptions = {
|
|
720
656
|
name: s.name,
|
|
721
|
-
type: 'pie',
|
|
722
657
|
radius: [`${inner}%`, `${outer}%`],
|
|
723
|
-
center: ['50%', '50%'],
|
|
724
|
-
avoidLabelOverlap: true,
|
|
725
|
-
minAngle: 3,
|
|
726
|
-
selectedMode: 'single',
|
|
727
|
-
selectedOffset: 4,
|
|
728
658
|
itemStyle: {
|
|
729
659
|
borderRadius: borderRadius,
|
|
730
|
-
|
|
731
|
-
borderWidth: borderWidth
|
|
660
|
+
borderWidth: borderWidth,
|
|
732
661
|
},
|
|
733
|
-
label: { show: false },
|
|
734
662
|
emphasis: {
|
|
735
|
-
scale: true,
|
|
736
|
-
scaleSize: 2,
|
|
737
663
|
itemStyle: {
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
}
|
|
664
|
+
borderWidth: borderWidth,
|
|
665
|
+
},
|
|
741
666
|
},
|
|
742
667
|
select: {
|
|
743
668
|
itemStyle: {
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
}
|
|
669
|
+
borderWidth: borderWidth,
|
|
670
|
+
},
|
|
747
671
|
},
|
|
748
|
-
animationType: 'scale',
|
|
749
|
-
animationEasing: 'elasticOut',
|
|
750
672
|
data: pieData,
|
|
751
|
-
id: `ring_${ringIndex}
|
|
673
|
+
id: `ring_${ringIndex}`,
|
|
752
674
|
};
|
|
675
|
+
const seriesOption = merge(dynamicRingSeriesOptions, overrides);
|
|
753
676
|
// Inyectar el resolver de color si existe
|
|
754
|
-
if (this.colorResolver) {
|
|
677
|
+
if (this.colorResolver && seriesOption.itemStyle) {
|
|
755
678
|
seriesOption.itemStyle.color = this.colorResolver;
|
|
756
679
|
}
|
|
757
680
|
return seriesOption;
|
|
758
681
|
});
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
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}%)`;
|
|
770
715
|
},
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
}
|
|
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.product;
|
|
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.product;
|
|
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.product;
|
|
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.product;
|
|
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();
|
|
794
843
|
}
|
|
795
844
|
}
|
|
796
845
|
|
|
@@ -801,14 +850,49 @@ class RingBuilder extends BaseEchartBuilder {
|
|
|
801
850
|
* @see {@link vs-echarts/docs/charts/ring-patterns.md}
|
|
802
851
|
*/
|
|
803
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
|
+
product = {
|
|
880
|
+
chartKey: 'ring',
|
|
881
|
+
baseOptions: {
|
|
882
|
+
series: this.baseSeriesOptions,
|
|
883
|
+
}
|
|
884
|
+
};
|
|
885
|
+
builder = new RingBuilder(this.product);
|
|
886
|
+
director = new VSECDirector(this.builder);
|
|
804
887
|
lastSelectedSeriesIndex = null;
|
|
805
888
|
lastSelectedDataIndex = null;
|
|
806
889
|
selectedPercent = null;
|
|
807
890
|
currentGraphicText = '';
|
|
808
|
-
builder;
|
|
809
891
|
constructor() {
|
|
810
892
|
super();
|
|
811
|
-
|
|
893
|
+
}
|
|
894
|
+
make(makeOpts) {
|
|
895
|
+
this.director.makeRing(this.data, this.optionsOverrides, makeOpts);
|
|
812
896
|
}
|
|
813
897
|
onInputChanges(changes) {
|
|
814
898
|
// Reset selection only if data changed
|
|
@@ -895,15 +979,14 @@ class EchartsRingComponent extends BaseEchartsComponent {
|
|
|
895
979
|
if (!this.data)
|
|
896
980
|
return;
|
|
897
981
|
// 1. Configuramos el builder (Formateadores, Colores, etc se manejan en la base)
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
this.
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
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);
|
|
905
988
|
// 2. Obtenemos las bases del chart usando el builder
|
|
906
|
-
let options = this.builder.
|
|
989
|
+
let options = this.builder.getResult();
|
|
907
990
|
// 3. Persistencia de GRAPHIC (KPI central)
|
|
908
991
|
if (options.graphic && Array.isArray(options.graphic)) {
|
|
909
992
|
const graphic = options.graphic[0];
|
|
@@ -946,359 +1029,276 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImpo
|
|
|
946
1029
|
}], ctorParameters: () => [] });
|
|
947
1030
|
|
|
948
1031
|
/**
|
|
949
|
-
*
|
|
1032
|
+
* Builder principal.
|
|
1033
|
+
*
|
|
1034
|
+
* Es muy completo, tiene soporte para ejes y sistema cartesiano polar.
|
|
950
1035
|
*
|
|
951
|
-
*
|
|
952
|
-
* @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.
|
|
953
1037
|
*/
|
|
954
|
-
class
|
|
955
|
-
|
|
956
|
-
|
|
1038
|
+
class EChartBuilder {
|
|
1039
|
+
product = undefined;
|
|
1040
|
+
valueFormatter = (value) => value.toLocaleString();
|
|
1041
|
+
palette = [];
|
|
1042
|
+
// TODO: Hay que implementar un valor por defecto.
|
|
1043
|
+
colorResolver;
|
|
1044
|
+
result = {};
|
|
1045
|
+
constructor(product) {
|
|
1046
|
+
this.product = product;
|
|
1047
|
+
}
|
|
1048
|
+
reset() {
|
|
1049
|
+
this.result = {};
|
|
1050
|
+
}
|
|
1051
|
+
addCommons() {
|
|
1052
|
+
const opts = {
|
|
1053
|
+
palette: this.palette,
|
|
1054
|
+
};
|
|
1055
|
+
merge$1(this.result, getCommons(opts));
|
|
957
1056
|
}
|
|
958
|
-
|
|
1057
|
+
/**
|
|
1058
|
+
*
|
|
1059
|
+
* @param data
|
|
1060
|
+
* @param overrides
|
|
1061
|
+
* @returns
|
|
1062
|
+
*/
|
|
1063
|
+
addSeries(data, overrides) {
|
|
959
1064
|
if (!data || !data.series.length)
|
|
960
|
-
return
|
|
1065
|
+
return;
|
|
961
1066
|
const series = data.series.map((s) => {
|
|
962
|
-
const
|
|
1067
|
+
const dynamicOverrides = {
|
|
963
1068
|
name: s.name,
|
|
964
|
-
type: 'bar',
|
|
965
|
-
barMaxWidth: 50,
|
|
966
|
-
barGap: '15%',
|
|
967
|
-
barCategoryGap: '35%',
|
|
968
|
-
animation: true,
|
|
969
|
-
animationDuration: 1000,
|
|
970
|
-
animationEasing: 'cubicOut',
|
|
971
|
-
itemStyle: {
|
|
972
|
-
borderRadius: [4, 4, 0, 0]
|
|
973
|
-
},
|
|
974
1069
|
data: s.data,
|
|
975
|
-
emphasis: {
|
|
976
|
-
focus: 'none'
|
|
977
|
-
},
|
|
978
|
-
blur: {
|
|
979
|
-
itemStyle: {
|
|
980
|
-
opacity: 0.2
|
|
981
|
-
}
|
|
982
|
-
},
|
|
983
|
-
select: {
|
|
984
|
-
itemStyle: {
|
|
985
|
-
opacity: 1,
|
|
986
|
-
shadowBlur: 10,
|
|
987
|
-
shadowColor: 'rgba(0,0,0,0.3)'
|
|
988
|
-
}
|
|
989
|
-
},
|
|
990
1070
|
label: {
|
|
991
|
-
show: false,
|
|
992
|
-
position: 'top',
|
|
993
1071
|
formatter: (params) => {
|
|
994
1072
|
const key = s.originalKey || (data.categoryKeys ? data.categoryKeys[params.dataIndex] : String(params.dataIndex));
|
|
995
1073
|
return this.formatCellValue(params.value, key);
|
|
996
1074
|
}
|
|
997
1075
|
}
|
|
998
1076
|
};
|
|
1077
|
+
const seriesOption = merge$1(dynamicOverrides, overrides);
|
|
999
1078
|
// Inyectar el resolver de color si existe
|
|
1000
|
-
if (this.colorResolver) {
|
|
1079
|
+
if (this.colorResolver && seriesOption.itemStyle) {
|
|
1001
1080
|
seriesOption.itemStyle.color = this.colorResolver;
|
|
1002
1081
|
}
|
|
1003
1082
|
return seriesOption;
|
|
1004
1083
|
});
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
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,
|
|
1019
1137
|
},
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
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
|
+
}
|
|
1024
1150
|
};
|
|
1151
|
+
const radialAxisOptions = getValueAxisOptions(radiusAxisOverrides);
|
|
1152
|
+
radiusAxis.push(radialAxisOptions);
|
|
1153
|
+
this.result.radiusAxis = radiusAxis;
|
|
1025
1154
|
}
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
* Especialista en visualización de bandas/barras verticales.
|
|
1032
|
-
* Implementa patrones de interacción ZRender y resaltado de grupos.
|
|
1033
|
-
* @see {@link vs-echarts/docs/charts/vertical-bands-patterns.md}
|
|
1034
|
-
*/
|
|
1035
|
-
class EchartsVerticalBandsComponent extends BaseEchartsComponent {
|
|
1036
|
-
builder;
|
|
1037
|
-
constructor() {
|
|
1038
|
-
super();
|
|
1039
|
-
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;
|
|
1040
1160
|
}
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
this.setupAdditionalInteractions();
|
|
1161
|
+
addLegend() {
|
|
1162
|
+
this.result.legend = getLegendOptions();
|
|
1044
1163
|
}
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
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;
|
|
1050
1183
|
}
|
|
1051
|
-
super.onInputChanges(changes);
|
|
1052
1184
|
}
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
const pointInPixel = [params.offsetX, params.offsetY];
|
|
1061
|
-
if (this.chartInstance.containPixel('grid', pointInPixel)) {
|
|
1062
|
-
const xIndexResult = this.chartInstance.convertFromPixel({ xAxisIndex: 0 }, pointInPixel);
|
|
1063
|
-
const xIndex = Array.isArray(xIndexResult) ? xIndexResult[0] : xIndexResult;
|
|
1064
|
-
if (typeof xIndex === 'number' && xIndex >= 0) {
|
|
1065
|
-
this.handleSelection(xIndex, -1); // Use -1 or null to indicate sector selection without specific series
|
|
1066
|
-
}
|
|
1067
|
-
}
|
|
1068
|
-
}
|
|
1069
|
-
});
|
|
1070
|
-
// 2. Mouseover for Group Highlighting
|
|
1071
|
-
this.chartInstance.on('mouseover', (params) => {
|
|
1072
|
-
if (params.dataIndex !== undefined) {
|
|
1073
|
-
this.highlightSector(params.dataIndex);
|
|
1074
|
-
}
|
|
1075
|
-
});
|
|
1076
|
-
this.chartInstance.on('mouseout', () => {
|
|
1077
|
-
this.clearHighlight();
|
|
1078
|
-
});
|
|
1185
|
+
/**
|
|
1186
|
+
* Permite inyectar una paleta de colores básica.
|
|
1187
|
+
*/
|
|
1188
|
+
setPalette(palette) {
|
|
1189
|
+
if (palette) {
|
|
1190
|
+
this.palette = palette;
|
|
1191
|
+
}
|
|
1079
1192
|
}
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
dataIndex: index
|
|
1088
|
-
});
|
|
1193
|
+
/**
|
|
1194
|
+
* Permite inyectar un resolver de colores dinámico.
|
|
1195
|
+
*/
|
|
1196
|
+
setColorResolver(resolver) {
|
|
1197
|
+
if (resolver) {
|
|
1198
|
+
this.colorResolver = resolver;
|
|
1199
|
+
}
|
|
1089
1200
|
}
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
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;
|
|
1098
1213
|
}
|
|
1214
|
+
}
|
|
1215
|
+
|
|
1216
|
+
class EchartsBarComponent extends BaseEchartsComponent {
|
|
1099
1217
|
/**
|
|
1100
|
-
*
|
|
1218
|
+
* Opciones escenciales inmutables estaticas comunes a todos los charts de barras.
|
|
1101
1219
|
*/
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
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
|
+
product = {
|
|
1246
|
+
chartKey: 'bar',
|
|
1247
|
+
baseOptions: {
|
|
1248
|
+
series: this.baseSeriesOptions,
|
|
1106
1249
|
}
|
|
1250
|
+
};
|
|
1251
|
+
builder = new EChartBuilder(this.product);
|
|
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);
|
|
1107
1259
|
}
|
|
1108
1260
|
updateChartOptions() {
|
|
1109
1261
|
if (!this.chartInstance)
|
|
1110
1262
|
return;
|
|
1111
1263
|
if (!this.data)
|
|
1112
1264
|
return;
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
this.
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
// 2. Obtenemos las bases del chart usando el builder
|
|
1121
|
-
let baseOptions = this.builder.build(this.data, this.optionsOverrides);
|
|
1122
|
-
// 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();
|
|
1123
1272
|
if (this.currentLegendSelected && baseOptions.legend) {
|
|
1124
1273
|
baseOptions.legend.selected = { ...this.currentLegendSelected };
|
|
1125
1274
|
}
|
|
1126
|
-
// 4. Apply persistent selection style if a sector is selected
|
|
1127
1275
|
if (this.selectedCategoryIndex !== null && baseOptions.series) {
|
|
1128
|
-
const seriesArray = baseOptions.series;
|
|
1129
|
-
baseOptions.series = seriesArray.map((s, sIdx) => {
|
|
1130
|
-
if (s.type === 'bar' && Array.isArray(s.data)) {
|
|
1131
|
-
return {
|
|
1132
|
-
...s,
|
|
1133
|
-
emphasis: {
|
|
1134
|
-
disabled: true
|
|
1135
|
-
},
|
|
1136
|
-
data: s.data.map((val, idx) => {
|
|
1137
|
-
const isSelected = idx === this.selectedCategoryIndex;
|
|
1138
|
-
const isBarSelected = isSelected && sIdx === this.selectedSeriesIndex;
|
|
1139
|
-
const itemVal = (val && typeof val === 'object' && val.value !== undefined) ? val.value : val;
|
|
1140
|
-
return {
|
|
1141
|
-
value: itemVal,
|
|
1142
|
-
itemStyle: {
|
|
1143
|
-
opacity: isSelected ? (isBarSelected ? 1 : 0.5) : 0.15,
|
|
1144
|
-
borderWidth: 0
|
|
1145
|
-
}
|
|
1146
|
-
};
|
|
1147
|
-
})
|
|
1148
|
-
};
|
|
1149
|
-
}
|
|
1150
|
-
return s;
|
|
1151
|
-
});
|
|
1152
|
-
}
|
|
1153
|
-
this.triggerUpdate(baseOptions);
|
|
1154
|
-
}
|
|
1155
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: EchartsVerticalBandsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1156
|
-
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"] }] });
|
|
1157
|
-
}
|
|
1158
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: EchartsVerticalBandsComponent, decorators: [{
|
|
1159
|
-
type: Component,
|
|
1160
|
-
args: [{ selector: 'vs-echarts-vertical-bands', standalone: true, imports: [
|
|
1161
|
-
CommonModule,
|
|
1162
|
-
NgxEchartsDirective,
|
|
1163
|
-
], 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"] }]
|
|
1164
|
-
}], ctorParameters: () => [] });
|
|
1165
|
-
|
|
1166
|
-
/**
|
|
1167
|
-
* BarBuilder
|
|
1168
|
-
*
|
|
1169
|
-
* Especializado en construir opciones para gráficos de barras generales.
|
|
1170
|
-
*/
|
|
1171
|
-
class BarBuilder extends BaseEchartBuilder {
|
|
1172
|
-
constructor() {
|
|
1173
|
-
super();
|
|
1174
|
-
}
|
|
1175
|
-
build(data, overrides) {
|
|
1176
|
-
if (!data || !data.series.length)
|
|
1177
|
-
return {};
|
|
1178
|
-
const { itemStyle, emphasis = { focus: 'none' }, stack = undefined, showBackground = false, coordinateSystem = 'cartesian2d', } = overrides.bar.series;
|
|
1179
|
-
const itStBorderRadius = itemStyle?.borderRadius ?? [4, 4, 0, 0];
|
|
1180
|
-
const emphasisFocus = emphasis.focus ?? 'none';
|
|
1181
|
-
const series = data.series.map((s) => {
|
|
1182
|
-
const seriesOption = {
|
|
1183
|
-
name: s.name,
|
|
1184
|
-
type: 'bar',
|
|
1185
|
-
barMaxWidth: 50,
|
|
1186
|
-
barGap: '15%',
|
|
1187
|
-
barCategoryGap: '35%',
|
|
1188
|
-
animation: true,
|
|
1189
|
-
animationDuration: 1000,
|
|
1190
|
-
animationEasing: 'cubicOut',
|
|
1191
|
-
coordinateSystem,
|
|
1192
|
-
itemStyle: {
|
|
1193
|
-
borderRadius: itStBorderRadius,
|
|
1194
|
-
},
|
|
1195
|
-
data: s.data,
|
|
1196
|
-
stack,
|
|
1197
|
-
emphasis: {
|
|
1198
|
-
focus: emphasisFocus
|
|
1199
|
-
},
|
|
1200
|
-
showBackground,
|
|
1201
|
-
backgroundStyle: {
|
|
1202
|
-
color: 'rgba(180, 180, 180, 0.2)' // gris claro
|
|
1203
|
-
},
|
|
1204
|
-
label: {
|
|
1205
|
-
show: false,
|
|
1206
|
-
position: 'top',
|
|
1207
|
-
formatter: (params) => {
|
|
1208
|
-
const key = s.originalKey || (data.categoryKeys ? data.categoryKeys[params.dataIndex] : String(params.dataIndex));
|
|
1209
|
-
return this.formatCellValue(params.value, key);
|
|
1210
|
-
}
|
|
1211
|
-
}
|
|
1212
|
-
};
|
|
1213
|
-
// Inyectar el resolver de color si existe
|
|
1214
|
-
if (this.colorResolver && seriesOption.itemStyle) {
|
|
1215
|
-
seriesOption.itemStyle.color = this.colorResolver;
|
|
1216
|
-
}
|
|
1217
|
-
return seriesOption;
|
|
1218
|
-
});
|
|
1219
|
-
const common = this.getCommonOptions(overrides);
|
|
1220
|
-
const xAxis = [];
|
|
1221
|
-
const yAxis = [];
|
|
1222
|
-
const radiusAxis = [];
|
|
1223
|
-
const polar = [];
|
|
1224
|
-
const angleAxis = [];
|
|
1225
|
-
const categoryAxisOptionsOverrides = {
|
|
1226
|
-
...overrides.axis.categoryAxis[0],
|
|
1227
|
-
data: data.categories,
|
|
1228
|
-
};
|
|
1229
|
-
const categoryAxisOptions = getCategoryAxisOptions(categoryAxisOptionsOverrides);
|
|
1230
|
-
const valueAxisOptions = getValueAxisOptions();
|
|
1231
|
-
if (coordinateSystem == "polar") {
|
|
1232
|
-
// polar coord system.
|
|
1233
|
-
/** estilos exclusivos hardcodeados para el eje de valores del sistema de coordenadas polar*/
|
|
1234
|
-
const radiusAxisOverrides = {
|
|
1235
|
-
axisTick: {
|
|
1236
|
-
show: false,
|
|
1237
|
-
},
|
|
1238
|
-
axisLabel: {
|
|
1239
|
-
margin: 2,
|
|
1240
|
-
fontSize: 8,
|
|
1241
|
-
align: 'right',
|
|
1242
|
-
rotate: 20,
|
|
1243
|
-
verticalAlign: 'top',
|
|
1244
|
-
},
|
|
1245
|
-
axisLine: {
|
|
1246
|
-
lineStyle: {
|
|
1247
|
-
type: 'dashed',
|
|
1248
|
-
},
|
|
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
|
+
};
|
|
1249
1297
|
}
|
|
1250
|
-
|
|
1251
|
-
angleAxis.push(categoryAxisOptions);
|
|
1252
|
-
const radialAxisOptions = getValueAxisOptions(radiusAxisOverrides);
|
|
1253
|
-
radiusAxis.push(radialAxisOptions);
|
|
1254
|
-
polar.push({
|
|
1255
|
-
radius: '65%',
|
|
1256
|
-
center: ["50%", "44%"],
|
|
1298
|
+
return s;
|
|
1257
1299
|
});
|
|
1258
1300
|
}
|
|
1259
|
-
|
|
1260
|
-
// cartesian 2d coord system.
|
|
1261
|
-
if (overrides.bar.orientation === 'h') {
|
|
1262
|
-
xAxis.push(valueAxisOptions);
|
|
1263
|
-
yAxis.push(categoryAxisOptions);
|
|
1264
|
-
}
|
|
1265
|
-
else {
|
|
1266
|
-
xAxis.push(categoryAxisOptions);
|
|
1267
|
-
yAxis.push(valueAxisOptions);
|
|
1268
|
-
}
|
|
1269
|
-
}
|
|
1270
|
-
const { trigger = 'item' } = overrides.tooltip;
|
|
1271
|
-
const tooltipOptionsOverrides = {
|
|
1272
|
-
trigger,
|
|
1273
|
-
};
|
|
1274
|
-
return {
|
|
1275
|
-
...common,
|
|
1276
|
-
tooltip: {
|
|
1277
|
-
...getTooltipOptions(tooltipOptionsOverrides),
|
|
1278
|
-
formatter: getTooltipFormatter(trigger, data, this.formatCellValue.bind(this))
|
|
1279
|
-
},
|
|
1280
|
-
legend: getLegendOptions(),
|
|
1281
|
-
xAxis,
|
|
1282
|
-
yAxis,
|
|
1283
|
-
radiusAxis,
|
|
1284
|
-
angleAxis,
|
|
1285
|
-
polar,
|
|
1286
|
-
series: series
|
|
1287
|
-
};
|
|
1288
|
-
}
|
|
1289
|
-
}
|
|
1290
|
-
|
|
1291
|
-
/**
|
|
1292
|
-
* EchartsBarComponent
|
|
1293
|
-
*
|
|
1294
|
-
* Componente especialista para visualización de gráficos de barras.
|
|
1295
|
-
* Implementa patrones de interacción ZRender y resaltado de grupos.
|
|
1296
|
-
*/
|
|
1297
|
-
class EchartsBarComponent extends BaseEchartsComponent {
|
|
1298
|
-
builder;
|
|
1299
|
-
constructor() {
|
|
1300
|
-
super();
|
|
1301
|
-
this.builder = new BarBuilder();
|
|
1301
|
+
this.triggerUpdate(baseOptions);
|
|
1302
1302
|
}
|
|
1303
1303
|
onChartInit(instance) {
|
|
1304
1304
|
super.onChartInit(instance);
|
|
@@ -1355,49 +1355,6 @@ class EchartsBarComponent extends BaseEchartsComponent {
|
|
|
1355
1355
|
this.updateChartOptions();
|
|
1356
1356
|
}
|
|
1357
1357
|
}
|
|
1358
|
-
updateChartOptions() {
|
|
1359
|
-
if (!this.chartInstance)
|
|
1360
|
-
return;
|
|
1361
|
-
if (!this.data)
|
|
1362
|
-
return;
|
|
1363
|
-
if (this.valueFormatter)
|
|
1364
|
-
this.builder.setValueFormatter(this.valueFormatter);
|
|
1365
|
-
if (this.palette)
|
|
1366
|
-
this.builder.setPalette(this.palette);
|
|
1367
|
-
if (this.colorResolver)
|
|
1368
|
-
this.builder.setColorResolver(this.colorResolver);
|
|
1369
|
-
let baseOptions = this.builder.build(this.data, this.optionsOverrides);
|
|
1370
|
-
if (this.currentLegendSelected && baseOptions.legend) {
|
|
1371
|
-
baseOptions.legend.selected = { ...this.currentLegendSelected };
|
|
1372
|
-
}
|
|
1373
|
-
if (this.selectedCategoryIndex !== null && baseOptions.series) {
|
|
1374
|
-
const seriesArray = baseOptions.series;
|
|
1375
|
-
baseOptions.series = seriesArray.map((s, sIdx) => {
|
|
1376
|
-
if (s.type === 'bar' && Array.isArray(s.data)) {
|
|
1377
|
-
return {
|
|
1378
|
-
...s,
|
|
1379
|
-
emphasis: {
|
|
1380
|
-
disabled: true
|
|
1381
|
-
},
|
|
1382
|
-
data: s.data.map((val, idx) => {
|
|
1383
|
-
const isSelected = idx === this.selectedCategoryIndex;
|
|
1384
|
-
const isBarSelected = isSelected && sIdx === this.selectedSeriesIndex;
|
|
1385
|
-
const itemVal = (val && typeof val === 'object' && val.value !== undefined) ? val.value : val;
|
|
1386
|
-
return {
|
|
1387
|
-
value: itemVal,
|
|
1388
|
-
itemStyle: {
|
|
1389
|
-
opacity: isSelected ? (isBarSelected ? 1 : 0.5) : 0.15,
|
|
1390
|
-
borderWidth: 0
|
|
1391
|
-
}
|
|
1392
|
-
};
|
|
1393
|
-
})
|
|
1394
|
-
};
|
|
1395
|
-
}
|
|
1396
|
-
return s;
|
|
1397
|
-
});
|
|
1398
|
-
}
|
|
1399
|
-
this.triggerUpdate(baseOptions);
|
|
1400
|
-
}
|
|
1401
1358
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: EchartsBarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1402
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"] }] });
|
|
1403
1360
|
}
|
|
@@ -1409,86 +1366,258 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImpo
|
|
|
1409
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"] }]
|
|
1410
1367
|
}], ctorParameters: () => [] });
|
|
1411
1368
|
|
|
1412
|
-
class
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
itemStyle: {
|
|
1432
|
-
shadowColor: 'rgba(0, 0, 0, 0.2)',
|
|
1433
|
-
shadowBlur: 5,
|
|
1434
|
-
shadowOffsetY: 2,
|
|
1435
|
-
},
|
|
1436
|
-
lineStyle: {
|
|
1437
|
-
width: 2,
|
|
1438
|
-
shadowColor: 'rgba(0, 0, 0, 0.2)',
|
|
1439
|
-
shadowBlur: 8,
|
|
1440
|
-
shadowOffsetY: 6,
|
|
1441
|
-
cap: 'round',
|
|
1442
|
-
join: 'round',
|
|
1443
|
-
},
|
|
1444
|
-
emphasis: {
|
|
1445
|
-
focus: 'none',
|
|
1446
|
-
itemStyle: {
|
|
1447
|
-
borderWidth: 2,
|
|
1448
|
-
shadowBlur: 10,
|
|
1449
|
-
},
|
|
1450
|
-
lineStyle: {
|
|
1451
|
-
width: 4,
|
|
1452
|
-
shadowBlur: 12,
|
|
1453
|
-
}
|
|
1454
|
-
},
|
|
1455
|
-
areaStyle,
|
|
1456
|
-
stack,
|
|
1457
|
-
};
|
|
1458
|
-
// Inyectar el resolver de color si existe
|
|
1459
|
-
if (this.colorResolver && seriesOption.itemStyle != undefined) {
|
|
1460
|
-
seriesOption.itemStyle.color = this.colorResolver;
|
|
1461
|
-
}
|
|
1462
|
-
return seriesOption;
|
|
1463
|
-
});
|
|
1464
|
-
const common = this.getCommonOptions(overrides);
|
|
1465
|
-
const categoryAxisOptions = {
|
|
1466
|
-
...overrides.axis.categoryAxis[0],
|
|
1467
|
-
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
|
+
variantProduct = {
|
|
1377
|
+
chartKey: 'hBar',
|
|
1378
|
+
baseOptions: {
|
|
1379
|
+
series: this.variantSeriesOptionsBase,
|
|
1380
|
+
}
|
|
1381
|
+
};
|
|
1382
|
+
builder = new EChartBuilder(this.variantProduct);
|
|
1383
|
+
director = new VSECDirector(this.builder);
|
|
1384
|
+
make(makeOpts) {
|
|
1385
|
+
makeOpts.axisTypes = {
|
|
1386
|
+
x: 'value',
|
|
1387
|
+
y: 'category',
|
|
1468
1388
|
};
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
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
|
+
variantProduct = {
|
|
1414
|
+
chartKey: 'barStacked',
|
|
1415
|
+
baseOptions: {
|
|
1416
|
+
series: this.variantSeriesOptionsBase,
|
|
1417
|
+
}
|
|
1418
|
+
};
|
|
1419
|
+
builder = new EChartBuilder(this.variantProduct);
|
|
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
|
+
variantProduct = {
|
|
1444
|
+
chartKey: 'hBarStacked',
|
|
1445
|
+
baseOptions: {
|
|
1446
|
+
series: this.variantSeriesOptionsBase,
|
|
1447
|
+
}
|
|
1448
|
+
};
|
|
1449
|
+
builder = new EChartBuilder(this.variantProduct);
|
|
1450
|
+
director = new VSECDirector(this.builder);
|
|
1451
|
+
make(makeOpts) {
|
|
1452
|
+
makeOpts.axisTypes = {
|
|
1453
|
+
x: 'value',
|
|
1454
|
+
y: 'category',
|
|
1472
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
|
+
variantProduct = {
|
|
1482
|
+
chartKey: 'barStackedRadial',
|
|
1483
|
+
baseOptions: {
|
|
1484
|
+
series: this.variantSeriesOptionsBase,
|
|
1485
|
+
}
|
|
1486
|
+
};
|
|
1487
|
+
builder = new EChartBuilder(this.variantProduct);
|
|
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;
|
|
1473
1520
|
return {
|
|
1474
|
-
...
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
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
|
|
1478
1532
|
},
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
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
|
+
})
|
|
1483
1573
|
};
|
|
1484
|
-
}
|
|
1574
|
+
});
|
|
1485
1575
|
}
|
|
1486
1576
|
|
|
1487
1577
|
class EchartsLineComponent extends BaseEchartsComponent {
|
|
1488
|
-
|
|
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
|
+
product = {
|
|
1612
|
+
chartKey: 'line',
|
|
1613
|
+
baseOptions: {
|
|
1614
|
+
series: this.baseSeriesOptions,
|
|
1615
|
+
}
|
|
1616
|
+
};
|
|
1617
|
+
builder = new EChartBuilder(this.product);
|
|
1618
|
+
director = new VSECDirector(this.builder);
|
|
1489
1619
|
constructor() {
|
|
1490
1620
|
super();
|
|
1491
|
-
this.builder = new LineBuilder();
|
|
1492
1621
|
}
|
|
1493
1622
|
onInputChanges(changes) {
|
|
1494
1623
|
if (changes['data']) {
|
|
@@ -1498,41 +1627,96 @@ class EchartsLineComponent extends BaseEchartsComponent {
|
|
|
1498
1627
|
}
|
|
1499
1628
|
super.onInputChanges(changes);
|
|
1500
1629
|
}
|
|
1630
|
+
make(makeOpts) {
|
|
1631
|
+
this.director.makeLine(this.data, this.optionsOverrides, makeOpts);
|
|
1632
|
+
}
|
|
1501
1633
|
updateChartOptions() {
|
|
1502
1634
|
if (!this.chartInstance)
|
|
1503
1635
|
return;
|
|
1504
1636
|
if (!this.data)
|
|
1505
1637
|
return;
|
|
1506
|
-
// 1.
|
|
1507
|
-
|
|
1508
|
-
this.
|
|
1509
|
-
|
|
1510
|
-
this.
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
// 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
|
|
1516
1647
|
if (this.currentLegendSelected && baseOptions.legend) {
|
|
1517
1648
|
baseOptions.legend.selected = { ...this.currentLegendSelected };
|
|
1518
1649
|
}
|
|
1519
|
-
//
|
|
1650
|
+
//3. Apply persistent selection style if a point is selected
|
|
1520
1651
|
if (this.selectedCategoryIndex !== null && baseOptions.series) {
|
|
1521
1652
|
baseOptions.series = applyLineSelectionStyle(baseOptions.series, this.selectedCategoryIndex, this.selectedSeriesIndex);
|
|
1522
1653
|
}
|
|
1523
1654
|
this.triggerUpdate(baseOptions);
|
|
1524
1655
|
}
|
|
1525
1656
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: EchartsLineComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1526
|
-
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"] }] });
|
|
1527
1660
|
}
|
|
1528
1661
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: EchartsLineComponent, decorators: [{
|
|
1529
1662
|
type: Component,
|
|
1530
1663
|
args: [{ selector: 'vs-echarts-line', standalone: true, imports: [
|
|
1531
1664
|
CommonModule,
|
|
1532
1665
|
NgxEchartsDirective,
|
|
1533
|
-
], 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"] }]
|
|
1534
1669
|
}], ctorParameters: () => [] });
|
|
1535
1670
|
|
|
1671
|
+
class EChartsAreaComponent extends EchartsLineComponent {
|
|
1672
|
+
variantSeriesOptionsBase = merge$1(this.baseSeriesOptions, {
|
|
1673
|
+
smooth: true,
|
|
1674
|
+
areaStyle: {},
|
|
1675
|
+
});
|
|
1676
|
+
variantProduct = {
|
|
1677
|
+
chartKey: 'area',
|
|
1678
|
+
baseOptions: {
|
|
1679
|
+
series: this.variantSeriesOptionsBase,
|
|
1680
|
+
}
|
|
1681
|
+
};
|
|
1682
|
+
builder = new EChartBuilder(this.variantProduct);
|
|
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
|
+
variantProduct = {
|
|
1702
|
+
chartKey: 'areaStack',
|
|
1703
|
+
baseOptions: {
|
|
1704
|
+
series: this.variantSeriesOptionsBase,
|
|
1705
|
+
}
|
|
1706
|
+
};
|
|
1707
|
+
builder = new EChartBuilder(this.variantProduct);
|
|
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
|
+
|
|
1536
1720
|
// Interfaces de Inputs de Base EChart Component //
|
|
1537
1721
|
|
|
1538
1722
|
;
|
|
@@ -1547,5 +1731,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImpo
|
|
|
1547
1731
|
* Generated bundle index. Do not edit.
|
|
1548
1732
|
*/
|
|
1549
1733
|
|
|
1550
|
-
export { BaseEchartsComponent, EchartsBarComponent, EchartsLineComponent, EchartsRingComponent,
|
|
1734
|
+
export { BaseEchartsComponent, EChartsAreaComponent, EChartsAreaStackComponent, EChartsBarStackedComponent, EChartsBarStackedRadialComponent, EChartsHBarComponent, EChartsHBarStackedComponent, EchartsBarComponent, EchartsLineComponent, EchartsRingComponent, defaultOptionsOverrides, initializeEcharts, provideVSEcharts };
|
|
1551
1735
|
//# sourceMappingURL=visionaris-bruno-vs-echarts.mjs.map
|