@record-evolution/widget-gauge 1.7.35 → 1.7.36
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/dist/widget-gauge.js +250 -228
- package/dist/widget-gauge.js.map +1 -1
- package/package.json +1 -1
- package/src/widget-gauge.ts +108 -61
package/src/widget-gauge.ts
CHANGED
|
@@ -32,7 +32,12 @@ class WidgetGauge extends LitElement {
|
|
|
32
32
|
@state()
|
|
33
33
|
private canvasList: Map<
|
|
34
34
|
string,
|
|
35
|
-
{
|
|
35
|
+
{
|
|
36
|
+
echart?: echarts.ECharts
|
|
37
|
+
title?: HTMLHeadingElement
|
|
38
|
+
wrapper?: HTMLDivElement
|
|
39
|
+
lastConfig?: string
|
|
40
|
+
}
|
|
36
41
|
> = new Map()
|
|
37
42
|
|
|
38
43
|
@state() private themeBgColor?: string
|
|
@@ -258,20 +263,23 @@ class WidgetGauge extends LitElement {
|
|
|
258
263
|
// )
|
|
259
264
|
this.boxes = Array.from(this.gaugeContainer?.querySelectorAll('.chart') as NodeListOf<HTMLDivElement>)
|
|
260
265
|
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
266
|
+
const gridColumns = `repeat(${fit.c}, 1fr)`
|
|
267
|
+
if (this.gaugeContainer.style.gridTemplateColumns !== gridColumns)
|
|
268
|
+
this.gaugeContainer.style.gridTemplateColumns = gridColumns
|
|
269
|
+
|
|
270
|
+
// This runs on every data tick, not just on real resizes. Touching the
|
|
271
|
+
// style attribute and calling echart.resize() when nothing changed is
|
|
272
|
+
// not free: each resize is a full unanimated re-render that also snaps
|
|
273
|
+
// any running gauge animation, so six gauges hitched on every update.
|
|
274
|
+
// Only boxes whose target size actually differs are written and resized.
|
|
275
|
+
const boxStyle = `width:${modifier * chartW}px; height:${modifier * (chartH - this.textContainerHeight)}px`
|
|
276
|
+
this.boxes?.forEach((box) => {
|
|
277
|
+
if (box.getAttribute('style') === boxStyle) return
|
|
278
|
+
box.setAttribute('style', boxStyle)
|
|
279
|
+
echarts.getInstanceByDom(box)?.resize()
|
|
280
|
+
})
|
|
269
281
|
|
|
270
282
|
this.modifier = modifier
|
|
271
|
-
|
|
272
|
-
this.canvasList.forEach((canvasObj) => {
|
|
273
|
-
canvasObj.echart?.resize()
|
|
274
|
-
})
|
|
275
283
|
}
|
|
276
284
|
|
|
277
285
|
async transformData() {
|
|
@@ -336,45 +344,16 @@ class WidgetGauge extends LitElement {
|
|
|
336
344
|
}
|
|
337
345
|
ds.needleValue = isNaN(ds.needleValue as number) ? gaugeMin : ds.needleValue
|
|
338
346
|
|
|
339
|
-
|
|
340
|
-
//
|
|
341
|
-
//
|
|
342
|
-
//
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
// and ECharts would merge that back one level deeper each update until
|
|
346
|
-
// zrender's recursive merge() overflowed the stack. Both gauge series
|
|
347
|
-
// and every nested key touched below are declared in the template, so
|
|
348
|
-
// a clone of it is a complete option in its own right.
|
|
349
|
-
const option = window.structuredClone(this.template)
|
|
350
|
-
const seriesArr = option.series as GaugeSeriesOption[]
|
|
351
|
-
const ga: any = seriesArr?.[0],
|
|
352
|
-
ga2: any = seriesArr?.[1]
|
|
353
|
-
|
|
354
|
-
// Needle
|
|
355
|
-
// Check age of data Latency
|
|
356
|
-
const tsp = Date.parse(ds?.data?.[0]?.tsp ?? '')
|
|
357
|
-
if (isNaN(tsp)) {
|
|
347
|
+
// Blank the gauge when the data is stale. The newest row sits at the
|
|
348
|
+
// END of the data array (the needle averages `slice(-averageLatest)`),
|
|
349
|
+
// so that is the row whose age matters. Rows without a parseable tsp
|
|
350
|
+
// opt out of the check — without timestamps age cannot be judged.
|
|
351
|
+
const tsp = Date.parse(ds.data?.[ds.data.length - 1]?.tsp ?? '')
|
|
352
|
+
if (!isNaN(tsp)) {
|
|
358
353
|
const now = new Date().getTime()
|
|
359
354
|
if (now - tsp > (ds.advanced?.maxLatency ?? Infinity) * 1000) ds.needleValue = undefined
|
|
360
355
|
}
|
|
361
356
|
|
|
362
|
-
ga.data[0].value = ds.needleValue
|
|
363
|
-
ga.data[0].name = ds.unit
|
|
364
|
-
// unit style
|
|
365
|
-
|
|
366
|
-
ga.title.fontSize = 32 * modifier
|
|
367
|
-
ga.title.color = ds.valueColor || this.themeTitleColor
|
|
368
|
-
ga.title.opacity = 1
|
|
369
|
-
// value style
|
|
370
|
-
ga.detail.color = ds.valueColor || this.themeTitleColor
|
|
371
|
-
ga.detail.opacity = 1
|
|
372
|
-
ga.detail.fontSize = 60 * modifier
|
|
373
|
-
|
|
374
|
-
ga.detail.formatter = (val: number) => {
|
|
375
|
-
const num = Number(val)
|
|
376
|
-
return isNaN(num) ? '-' : num.toFixed(Math.floor(ds.precision ?? 0))
|
|
377
|
-
}
|
|
378
357
|
// Axis
|
|
379
358
|
const defaultColors = ['#bf444c', '#d88273', '#f6efa6']
|
|
380
359
|
const themeColors = this.theme?.theme_object?.color ?? defaultColors
|
|
@@ -409,9 +388,6 @@ class WidgetGauge extends LitElement {
|
|
|
409
388
|
const gaugeMax = sectionLimits?.[sectionLimits.length - 1] ?? 100
|
|
410
389
|
ds.range = Math.abs(gaugeMax - gaugeMin)
|
|
411
390
|
|
|
412
|
-
ga.min = ga2.min = gaugeMin
|
|
413
|
-
ga.max = ga2.max = gaugeMax
|
|
414
|
-
|
|
415
391
|
// percentages of the sections paired with the colors (must be strictly ascending for ECharts)
|
|
416
392
|
const colorSections = sectionLimits
|
|
417
393
|
.map((limit, i) => {
|
|
@@ -421,14 +397,6 @@ class WidgetGauge extends LitElement {
|
|
|
421
397
|
})
|
|
422
398
|
.filter(([s]) => !isNaN(s) && s >= 0)
|
|
423
399
|
|
|
424
|
-
ga2.axisLine.lineStyle.width = 8 * modifier
|
|
425
|
-
if (colorSections.length) ga2.axisLine.lineStyle.color = colorSections
|
|
426
|
-
ga2.axisLabel.fontSize = 24 * modifier
|
|
427
|
-
// ga2.axisLabel.color = ds.valueColor
|
|
428
|
-
ga2.axisLabel.distance = -24 * modifier
|
|
429
|
-
ga2.splitLine.length = 16 * modifier
|
|
430
|
-
ga2.splitLine.distance = -16 * modifier
|
|
431
|
-
|
|
432
400
|
// Progress
|
|
433
401
|
let progressColor = colors?.[colors.length - 1]
|
|
434
402
|
for (const [i, s] of sectionLimits?.entries() ?? []) {
|
|
@@ -440,10 +408,89 @@ class WidgetGauge extends LitElement {
|
|
|
440
408
|
break
|
|
441
409
|
}
|
|
442
410
|
}
|
|
411
|
+
|
|
412
|
+
const canvas = this.canvasList.get(ds.label)
|
|
413
|
+
const echart = canvas?.echart
|
|
414
|
+
|
|
415
|
+
// On a live dashboard this loop runs for every gauge on every data
|
|
416
|
+
// tick, so the steady-state path has to stay off the expensive
|
|
417
|
+
// full-option merge: everything below except the needle value and
|
|
418
|
+
// the progress color is configuration that only changes with the
|
|
419
|
+
// container size (modifier), the widget config, or the theme. When
|
|
420
|
+
// that signature is unchanged, send ECharts only the two values
|
|
421
|
+
// that move; the stored option keeps everything else. lazyUpdate
|
|
422
|
+
// defers processing to the next animation frame so several gauges
|
|
423
|
+
// updating in the same tick do not each force a synchronous render.
|
|
424
|
+
const configSig = JSON.stringify([
|
|
425
|
+
modifier,
|
|
426
|
+
ds.unit,
|
|
427
|
+
ds.precision,
|
|
428
|
+
ds.valueColor,
|
|
429
|
+
ds.sections,
|
|
430
|
+
this.themeTitleColor
|
|
431
|
+
])
|
|
432
|
+
if (canvas && canvas.lastConfig === configSig) {
|
|
433
|
+
echart?.setOption(
|
|
434
|
+
{
|
|
435
|
+
series: [
|
|
436
|
+
{
|
|
437
|
+
data: [{ value: ds.needleValue ?? null, name: ds.unit }],
|
|
438
|
+
progress: { itemStyle: { color: progressColor } }
|
|
439
|
+
}
|
|
440
|
+
]
|
|
441
|
+
},
|
|
442
|
+
{ lazyUpdate: true }
|
|
443
|
+
)
|
|
444
|
+
continue
|
|
445
|
+
}
|
|
446
|
+
if (canvas) canvas.lastConfig = configSig
|
|
447
|
+
|
|
448
|
+
// Always build the option from the template — never from getOption().
|
|
449
|
+
// Reading the rendered option back and handing it to setOption looks
|
|
450
|
+
// cheap but is not: getOption() deep-clones the whole stored option on
|
|
451
|
+
// every frame, and it normalizes every component to an array, so any
|
|
452
|
+
// future `{ ...option.x }` here would spread an array into `{ '0': x }`
|
|
453
|
+
// and ECharts would merge that back one level deeper each update until
|
|
454
|
+
// zrender's recursive merge() overflowed the stack. Both gauge series
|
|
455
|
+
// and every nested key touched below are declared in the template, so
|
|
456
|
+
// a clone of it is a complete option in its own right.
|
|
457
|
+
const option = window.structuredClone(this.template)
|
|
458
|
+
const seriesArr = option.series as GaugeSeriesOption[]
|
|
459
|
+
const ga: any = seriesArr?.[0],
|
|
460
|
+
ga2: any = seriesArr?.[1]
|
|
461
|
+
|
|
462
|
+
ga.data[0].value = ds.needleValue
|
|
463
|
+
ga.data[0].name = ds.unit
|
|
464
|
+
// unit style
|
|
465
|
+
|
|
466
|
+
ga.title.fontSize = 32 * modifier
|
|
467
|
+
ga.title.color = ds.valueColor || this.themeTitleColor
|
|
468
|
+
ga.title.opacity = 1
|
|
469
|
+
// value style
|
|
470
|
+
ga.detail.color = ds.valueColor || this.themeTitleColor
|
|
471
|
+
ga.detail.opacity = 1
|
|
472
|
+
ga.detail.fontSize = 60 * modifier
|
|
473
|
+
|
|
474
|
+
ga.detail.formatter = (val: number) => {
|
|
475
|
+
const num = Number(val)
|
|
476
|
+
return isNaN(num) ? '-' : num.toFixed(Math.floor(ds.precision ?? 0))
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
ga.min = ga2.min = gaugeMin
|
|
480
|
+
ga.max = ga2.max = gaugeMax
|
|
481
|
+
|
|
482
|
+
ga2.axisLine.lineStyle.width = 8 * modifier
|
|
483
|
+
if (colorSections.length) ga2.axisLine.lineStyle.color = colorSections
|
|
484
|
+
ga2.axisLabel.fontSize = 24 * modifier
|
|
485
|
+
// ga2.axisLabel.color = ds.valueColor
|
|
486
|
+
ga2.axisLabel.distance = -24 * modifier
|
|
487
|
+
ga2.splitLine.length = 16 * modifier
|
|
488
|
+
ga2.splitLine.distance = -16 * modifier
|
|
489
|
+
|
|
443
490
|
ga.progress.itemStyle.color = progressColor
|
|
444
491
|
ga.progress.width = 60 * modifier
|
|
445
492
|
|
|
446
|
-
const titleElement =
|
|
493
|
+
const titleElement = canvas?.title
|
|
447
494
|
if (titleElement) {
|
|
448
495
|
titleElement.style.fontSize = String(36 * modifier) + 'px'
|
|
449
496
|
titleElement.style.maxWidth = String(550 * modifier) + 'px'
|
|
@@ -452,7 +499,7 @@ class WidgetGauge extends LitElement {
|
|
|
452
499
|
}
|
|
453
500
|
|
|
454
501
|
// Apply
|
|
455
|
-
echart?.setOption(option)
|
|
502
|
+
echart?.setOption(option, { lazyUpdate: true })
|
|
456
503
|
}
|
|
457
504
|
}
|
|
458
505
|
deleteCharts() {
|