mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-20 07:46:37 +00:00
Make part of the chart rendering async for large datasets (#24260)
This commit is contained in:
parent
cdd17eed2e
commit
c52217c1ce
@ -6,7 +6,6 @@ import type { DataZoomComponentOption } from "echarts/components";
|
||||
import type { EChartsType } from "echarts/core";
|
||||
import type {
|
||||
ECElementEvent,
|
||||
SetOptionOpts,
|
||||
XAXisOption,
|
||||
YAXisOption,
|
||||
} from "echarts/types/dist/shared";
|
||||
@ -25,6 +24,7 @@ import type { HomeAssistant } from "../../types";
|
||||
import { isMac } from "../../util/is_mac";
|
||||
import "../ha-icon-button";
|
||||
import { formatTimeLabel } from "./axis-label";
|
||||
import { ensureArray } from "../../common/array/ensure-array";
|
||||
|
||||
export const MIN_TIME_BETWEEN_UPDATES = 60 * 5 * 1000;
|
||||
|
||||
@ -68,12 +68,16 @@ export class HaChartBase extends LitElement {
|
||||
|
||||
private _listeners: (() => void)[] = [];
|
||||
|
||||
private _originalZrFlush?: () => void;
|
||||
|
||||
public disconnectedCallback() {
|
||||
super.disconnectedCallback();
|
||||
while (this._listeners.length) {
|
||||
this._listeners.pop()!();
|
||||
}
|
||||
this.chart?.dispose();
|
||||
this.chart = undefined;
|
||||
this._originalZrFlush = undefined;
|
||||
}
|
||||
|
||||
public connectedCallback() {
|
||||
@ -86,7 +90,7 @@ export class HaChartBase extends LitElement {
|
||||
listenMediaQuery("(prefers-reduced-motion)", (matches) => {
|
||||
if (this._reducedMotion !== matches) {
|
||||
this._reducedMotion = matches;
|
||||
this.chart?.setOption({ animation: !this._reducedMotion });
|
||||
this._setChartOptions({ animation: !this._reducedMotion });
|
||||
}
|
||||
})
|
||||
);
|
||||
@ -96,7 +100,7 @@ export class HaChartBase extends LitElement {
|
||||
if ((isMac && ev.key === "Meta") || (!isMac && ev.key === "Control")) {
|
||||
this._modifierPressed = true;
|
||||
if (!this.options?.dataZoom) {
|
||||
this.chart?.setOption({ dataZoom: this._getDataZoomConfig() });
|
||||
this._setChartOptions({ dataZoom: this._getDataZoomConfig() });
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -105,7 +109,7 @@ export class HaChartBase extends LitElement {
|
||||
if ((isMac && ev.key === "Meta") || (!isMac && ev.key === "Control")) {
|
||||
this._modifierPressed = false;
|
||||
if (!this.options?.dataZoom) {
|
||||
this.chart?.setOption({ dataZoom: this._getDataZoomConfig() });
|
||||
this._setChartOptions({ dataZoom: this._getDataZoomConfig() });
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -131,10 +135,8 @@ export class HaChartBase extends LitElement {
|
||||
return;
|
||||
}
|
||||
let chartOptions: ECOption = {};
|
||||
const chartUpdateParams: SetOptionOpts = { lazyUpdate: true };
|
||||
if (changedProps.has("data")) {
|
||||
chartOptions.series = this.data;
|
||||
chartUpdateParams.replaceMerge = ["series"];
|
||||
}
|
||||
if (changedProps.has("options")) {
|
||||
chartOptions = { ...chartOptions, ...this._createOptions() };
|
||||
@ -142,7 +144,7 @@ export class HaChartBase extends LitElement {
|
||||
chartOptions.dataZoom = this._getDataZoomConfig();
|
||||
}
|
||||
if (Object.keys(chartOptions).length > 0) {
|
||||
this.chart.setOption(chartOptions, chartUpdateParams);
|
||||
this._setChartOptions(chartOptions);
|
||||
}
|
||||
}
|
||||
|
||||
@ -509,6 +511,31 @@ export class HaChartBase extends LitElement {
|
||||
return Math.max(this.clientWidth / 2, 200);
|
||||
}
|
||||
|
||||
private _setChartOptions(options: ECOption) {
|
||||
if (!this.chart) {
|
||||
return;
|
||||
}
|
||||
if (!this._originalZrFlush) {
|
||||
const dataSize = ensureArray(this.data).reduce(
|
||||
(acc, series) => acc + (series.data as any[]).length,
|
||||
0
|
||||
);
|
||||
if (dataSize > 10000) {
|
||||
// for large datasets zr.flush takes 30-40% of the render time
|
||||
// so we delay it a bit to avoid blocking the main thread
|
||||
const zr = this.chart.getZr();
|
||||
this._originalZrFlush = zr.flush.bind(zr);
|
||||
zr.flush = () => {
|
||||
setTimeout(() => {
|
||||
this._originalZrFlush?.();
|
||||
}, 10);
|
||||
};
|
||||
}
|
||||
}
|
||||
const replaceMerge = options.series ? ["series"] : [];
|
||||
this.chart.setOption(options, { replaceMerge });
|
||||
}
|
||||
|
||||
private _handleZoomReset() {
|
||||
this.chart?.dispatchAction({ type: "dataZoom", start: 0, end: 100 });
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user