162 lines
4.1 KiB
TypeScript
162 lines
4.1 KiB
TypeScript
import {
|
|
customElement,
|
|
property,
|
|
type TemplateResult,
|
|
} from '@design.estate/dees-element';
|
|
|
|
import { DeesChartEchartsBase } from '../dees-chart-echarts-base.js';
|
|
import { demoFunc } from './demo.js';
|
|
import { gaugeStyles } from './styles.js';
|
|
import { renderChartGauge } from './template.js';
|
|
import { getEchartsSeriesColors } from '../dees-chart-echarts-theme.js';
|
|
|
|
export interface IGaugeThreshold {
|
|
value: number;
|
|
color: string;
|
|
}
|
|
|
|
declare global {
|
|
interface HTMLElementTagNameMap {
|
|
'dees-chart-gauge': DeesChartGauge;
|
|
}
|
|
}
|
|
|
|
@customElement('dees-chart-gauge')
|
|
export class DeesChartGauge extends DeesChartEchartsBase {
|
|
public static demo = demoFunc;
|
|
public static demoGroups = ['Chart'];
|
|
|
|
@property({ type: Number })
|
|
accessor value: number = 0;
|
|
|
|
@property({ type: Number })
|
|
accessor min: number = 0;
|
|
|
|
@property({ type: Number })
|
|
accessor max: number = 100;
|
|
|
|
@property({ type: String })
|
|
accessor unit: string = '%';
|
|
|
|
@property({ type: Array })
|
|
accessor thresholds: IGaugeThreshold[] = [];
|
|
|
|
@property({ type: Boolean })
|
|
accessor showTicks: boolean = true;
|
|
|
|
public static styles = gaugeStyles;
|
|
|
|
public render(): TemplateResult {
|
|
return renderChartGauge(this);
|
|
}
|
|
|
|
public async updated(changedProperties: Map<string, any>) {
|
|
super.updated(changedProperties);
|
|
if (
|
|
this.chartInstance &&
|
|
(changedProperties.has('value') ||
|
|
changedProperties.has('min') ||
|
|
changedProperties.has('max') ||
|
|
changedProperties.has('unit') ||
|
|
changedProperties.has('thresholds') ||
|
|
changedProperties.has('showTicks'))
|
|
) {
|
|
this.updateChart();
|
|
}
|
|
}
|
|
|
|
protected buildOption(): Record<string, any> {
|
|
const isDark = !this.goBright;
|
|
const seriesColors = getEchartsSeriesColors(this.goBright);
|
|
const primaryColor = seriesColors[0];
|
|
|
|
// Build axis line color stops from thresholds
|
|
let axisLineColors: Array<[number, string]>;
|
|
if (this.thresholds.length > 0) {
|
|
const sorted = [...this.thresholds].sort((a, b) => a.value - b.value);
|
|
axisLineColors = sorted.map((t) => [
|
|
(t.value - this.min) / (this.max - this.min),
|
|
t.color,
|
|
]);
|
|
// Ensure we end at 1
|
|
if (axisLineColors[axisLineColors.length - 1][0] < 1) {
|
|
axisLineColors.push([1, sorted[sorted.length - 1].color]);
|
|
}
|
|
} else {
|
|
axisLineColors = [[1, primaryColor]];
|
|
}
|
|
|
|
return {
|
|
series: [
|
|
{
|
|
type: 'gauge',
|
|
min: this.min,
|
|
max: this.max,
|
|
startAngle: 220,
|
|
endAngle: -40,
|
|
progress: {
|
|
show: true,
|
|
width: 14,
|
|
roundCap: true,
|
|
},
|
|
pointer: {
|
|
show: true,
|
|
length: '60%',
|
|
width: 5,
|
|
itemStyle: {
|
|
color: 'auto',
|
|
},
|
|
},
|
|
axisLine: {
|
|
lineStyle: {
|
|
width: 14,
|
|
color: axisLineColors,
|
|
opacity: 0.3,
|
|
},
|
|
},
|
|
axisTick: {
|
|
show: this.showTicks,
|
|
distance: -20,
|
|
length: 6,
|
|
lineStyle: {
|
|
color: isDark ? 'hsl(0 0% 30%)' : 'hsl(0 0% 75%)',
|
|
width: 1,
|
|
},
|
|
},
|
|
splitLine: {
|
|
show: this.showTicks,
|
|
distance: -24,
|
|
length: 10,
|
|
lineStyle: {
|
|
color: isDark ? 'hsl(0 0% 40%)' : 'hsl(0 0% 60%)',
|
|
width: 2,
|
|
},
|
|
},
|
|
axisLabel: {
|
|
show: this.showTicks,
|
|
distance: 30,
|
|
color: isDark ? 'hsl(0 0% 50%)' : 'hsl(0 0% 45%)',
|
|
fontSize: 11,
|
|
},
|
|
detail: {
|
|
valueAnimation: true,
|
|
fontSize: 28,
|
|
fontWeight: 600,
|
|
offsetCenter: [0, '65%'],
|
|
color: isDark ? 'hsl(0 0% 90%)' : 'hsl(0 0% 15%)',
|
|
formatter: `{value}${this.unit}`,
|
|
},
|
|
title: {
|
|
show: false,
|
|
},
|
|
data: [
|
|
{
|
|
value: this.value,
|
|
},
|
|
],
|
|
},
|
|
],
|
|
};
|
|
}
|
|
}
|