update
This commit is contained in:
107
ts_web/elements/00group-chart/dees-chart-echarts-base.ts
Normal file
107
ts_web/elements/00group-chart/dees-chart-echarts-base.ts
Normal file
@@ -0,0 +1,107 @@
|
||||
import {
|
||||
DeesElement,
|
||||
property,
|
||||
html,
|
||||
type TemplateResult,
|
||||
} from '@design.estate/dees-element';
|
||||
|
||||
import * as domtools from '@design.estate/dees-domtools';
|
||||
import { DeesServiceLibLoader, type IEchartsBundle, type IEchartsInstance } from '../../services/index.js';
|
||||
import { getEchartsThemeOptions } from './dees-chart-echarts-theme.js';
|
||||
import '../00group-layout/dees-tile/dees-tile.js';
|
||||
|
||||
/**
|
||||
* Abstract base class for ECharts-based chart components.
|
||||
* Handles library loading, chart lifecycle, resize observation, and theme switching.
|
||||
* Subclasses implement `buildOption()` to define their chart configuration.
|
||||
*/
|
||||
export abstract class DeesChartEchartsBase extends DeesElement {
|
||||
@property()
|
||||
accessor label: string = 'Untitled Chart';
|
||||
|
||||
protected chartInstance: IEchartsInstance | null = null;
|
||||
protected echartsBundle: IEchartsBundle | null = null;
|
||||
private resizeObserver: ResizeObserver | null = null;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
domtools.elementBasic.setup();
|
||||
this.registerGarbageFunction(async () => {
|
||||
if (this.resizeObserver) {
|
||||
this.resizeObserver.disconnect();
|
||||
this.resizeObserver = null;
|
||||
}
|
||||
if (this.chartInstance) {
|
||||
try {
|
||||
this.chartInstance.dispose();
|
||||
this.chartInstance = null;
|
||||
} catch (e) {
|
||||
console.error('Error disposing ECharts instance:', e);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public render(): TemplateResult {
|
||||
return html`
|
||||
<dees-tile>
|
||||
<div slot="header" class="chartHeader">
|
||||
<span class="chartLabel">${this.label}</span>
|
||||
</div>
|
||||
<div class="chartContainer"></div>
|
||||
</dees-tile>
|
||||
`;
|
||||
}
|
||||
|
||||
public async firstUpdated() {
|
||||
await this.domtoolsPromise;
|
||||
this.echartsBundle = await DeesServiceLibLoader.getInstance().loadEcharts();
|
||||
await new Promise(resolve => requestAnimationFrame(resolve));
|
||||
|
||||
const chartContainer = this.shadowRoot!.querySelector('.chartContainer') as HTMLDivElement;
|
||||
if (!chartContainer) return;
|
||||
|
||||
try {
|
||||
this.chartInstance = this.echartsBundle.init(chartContainer);
|
||||
this.updateChart();
|
||||
|
||||
this.resizeObserver = new ResizeObserver(() => {
|
||||
this.chartInstance?.resize();
|
||||
});
|
||||
this.resizeObserver.observe(chartContainer);
|
||||
} catch (error) {
|
||||
console.error('Failed to initialize ECharts:', error);
|
||||
}
|
||||
}
|
||||
|
||||
public async updated(changedProperties: Map<string, any>) {
|
||||
super.updated(changedProperties);
|
||||
if (changedProperties.has('goBright') && this.chartInstance) {
|
||||
this.applyTheme();
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract buildOption(): Record<string, any>;
|
||||
|
||||
protected updateChart(): void {
|
||||
if (!this.chartInstance) return;
|
||||
const themeOptions = getEchartsThemeOptions(this.goBright);
|
||||
const chartOption = this.buildOption();
|
||||
// Merge theme defaults with chart-specific options
|
||||
const merged = {
|
||||
...themeOptions,
|
||||
...chartOption,
|
||||
textStyle: { ...themeOptions.textStyle, ...(chartOption.textStyle || {}) },
|
||||
tooltip: { ...themeOptions.tooltip, ...(chartOption.tooltip || {}) },
|
||||
};
|
||||
this.chartInstance.setOption(merged, true);
|
||||
}
|
||||
|
||||
protected applyTheme(): void {
|
||||
this.updateChart();
|
||||
}
|
||||
|
||||
public async forceResize(): Promise<void> {
|
||||
this.chartInstance?.resize();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user