diff --git a/src/components/chart/ha-chart-base.ts b/src/components/chart/ha-chart-base.ts
index 6f6f8a40aa..8ebea677b3 100644
--- a/src/components/chart/ha-chart-base.ts
+++ b/src/components/chart/ha-chart-base.ts
@@ -31,6 +31,7 @@ import "../chips/ha-assist-chip";
export const MIN_TIME_BETWEEN_UPDATES = 60 * 5 * 1000;
const LEGEND_OVERFLOW_LIMIT = 10;
const LEGEND_OVERFLOW_LIMIT_MOBILE = 6;
+const DOUBLE_TAP_TIME = 300;
@customElement("ha-chart-base")
export class HaChartBase extends LitElement {
@@ -65,6 +66,8 @@ export class HaChartBase extends LitElement {
private _isTouchDevice = "ontouchstart" in window;
+ private _lastTapTime?: number;
+
// @ts-ignore
private _resizeController = new ResizeController(this, {
callback: () => this.chart?.resize(),
@@ -110,6 +113,12 @@ export class HaChartBase extends LitElement {
if (!this.options?.dataZoom) {
this._setChartOptions({ dataZoom: this._getDataZoomConfig() });
}
+ // drag to zoom
+ this.chart?.dispatchAction({
+ type: "takeGlobalCursor",
+ key: "dataZoomSelect",
+ dataZoomSelectActive: true,
+ });
}
};
@@ -119,6 +128,11 @@ export class HaChartBase extends LitElement {
if (!this.options?.dataZoom) {
this._setChartOptions({ dataZoom: this._getDataZoomConfig() });
}
+ this.chart?.dispatchAction({
+ type: "takeGlobalCursor",
+ key: "dataZoomSelect",
+ dataZoomSelectActive: false,
+ });
}
};
@@ -160,9 +174,7 @@ export class HaChartBase extends LitElement {
return html`
{
fireEvent(this, "chart-click", e);
});
- this.chart.on("mousemove", (e: ECElementEvent) => {
- if (e.componentType === "series" && e.componentSubType === "custom") {
- // custom series do not support cursor style so we need to set it manually
- this.chart?.getZr()?.setCursorStyle("default");
- }
- });
+ this.chart.getZr().on("dblclick", this._handleClickZoom);
+ if (this._isTouchDevice) {
+ this.chart.getZr().on("click", (e: ECElementEvent) => {
+ if (!e.zrByTouch) {
+ return;
+ }
+ if (
+ this._lastTapTime &&
+ Date.now() - this._lastTapTime < DOUBLE_TAP_TIME
+ ) {
+ this._handleClickZoom(e);
+ } else {
+ this._lastTapTime = Date.now();
+ }
+ });
+ }
this.chart.setOption({
...this._createOptions(),
series: this._getSeries(),
@@ -350,20 +372,12 @@ export class HaChartBase extends LitElement {
: undefined;
}
return {
- axisLine: {
- show: false,
- },
- splitLine: {
- show: true,
- },
+ axisLine: { show: false },
+ splitLine: { show: true },
...axis,
axisLabel: {
formatter: this._formatTimeLabel,
- rich: {
- bold: {
- fontWeight: "bold",
- },
- },
+ rich: { bold: { fontWeight: "bold" } },
hideOverlap: true,
...axis.axisLabel,
},
@@ -374,14 +388,18 @@ export class HaChartBase extends LitElement {
const options = {
animation: !this._reducedMotion,
darkMode: this._themes.darkMode ?? false,
- aria: {
- show: true,
- },
+ aria: { show: true },
dataZoom: this._getDataZoomConfig(),
- ...this.options,
- legend: {
- show: false,
+ toolbox: {
+ top: Infinity,
+ left: Infinity,
+ feature: {
+ dataZoom: { show: true, yAxisIndex: false, filterMode: "none" },
+ },
+ iconStyle: { opacity: 0 },
},
+ ...this.options,
+ legend: { show: false },
xAxis,
};
@@ -413,42 +431,28 @@ export class HaChartBase extends LitElement {
fontFamily: "Roboto, Noto, sans-serif",
},
title: {
- textStyle: {
- color: style.getPropertyValue("--primary-text-color"),
- },
+ textStyle: { color: style.getPropertyValue("--primary-text-color") },
subtextStyle: {
color: style.getPropertyValue("--secondary-text-color"),
},
},
line: {
- lineStyle: {
- width: 1.5,
- },
+ lineStyle: { width: 1.5 },
symbolSize: 1,
symbol: "circle",
smooth: false,
},
- bar: {
- itemStyle: {
- barBorderWidth: 1.5,
- },
- },
+ bar: { itemStyle: { barBorderWidth: 1.5 } },
categoryAxis: {
- axisLine: {
- show: false,
- },
- axisTick: {
- show: false,
- },
+ axisLine: { show: false },
+ axisTick: { show: false },
axisLabel: {
show: true,
color: style.getPropertyValue("--primary-text-color"),
},
splitLine: {
show: false,
- lineStyle: {
- color: style.getPropertyValue("--divider-color"),
- },
+ lineStyle: { color: style.getPropertyValue("--divider-color") },
},
splitArea: {
show: false,
@@ -463,15 +467,11 @@ export class HaChartBase extends LitElement {
valueAxis: {
axisLine: {
show: true,
- lineStyle: {
- color: style.getPropertyValue("--divider-color"),
- },
+ lineStyle: { color: style.getPropertyValue("--divider-color") },
},
axisTick: {
show: true,
- lineStyle: {
- color: style.getPropertyValue("--divider-color"),
- },
+ lineStyle: { color: style.getPropertyValue("--divider-color") },
},
axisLabel: {
show: true,
@@ -479,9 +479,7 @@ export class HaChartBase extends LitElement {
},
splitLine: {
show: true,
- lineStyle: {
- color: style.getPropertyValue("--divider-color"),
- },
+ lineStyle: { color: style.getPropertyValue("--divider-color") },
},
splitArea: {
show: false,
@@ -496,15 +494,11 @@ export class HaChartBase extends LitElement {
logAxis: {
axisLine: {
show: true,
- lineStyle: {
- color: style.getPropertyValue("--divider-color"),
- },
+ lineStyle: { color: style.getPropertyValue("--divider-color") },
},
axisTick: {
show: true,
- lineStyle: {
- color: style.getPropertyValue("--divider-color"),
- },
+ lineStyle: { color: style.getPropertyValue("--divider-color") },
},
axisLabel: {
show: true,
@@ -512,9 +506,7 @@ export class HaChartBase extends LitElement {
},
splitLine: {
show: true,
- lineStyle: {
- color: style.getPropertyValue("--divider-color"),
- },
+ lineStyle: { color: style.getPropertyValue("--divider-color") },
},
splitArea: {
show: false,
@@ -529,15 +521,11 @@ export class HaChartBase extends LitElement {
timeAxis: {
axisLine: {
show: true,
- lineStyle: {
- color: style.getPropertyValue("--divider-color"),
- },
+ lineStyle: { color: style.getPropertyValue("--divider-color") },
},
axisTick: {
show: true,
- lineStyle: {
- color: style.getPropertyValue("--divider-color"),
- },
+ lineStyle: { color: style.getPropertyValue("--divider-color") },
},
axisLabel: {
show: true,
@@ -545,9 +533,7 @@ export class HaChartBase extends LitElement {
},
splitLine: {
show: true,
- lineStyle: {
- color: style.getPropertyValue("--divider-color"),
- },
+ lineStyle: { color: style.getPropertyValue("--divider-color") },
},
splitArea: {
show: false,
@@ -560,9 +546,7 @@ export class HaChartBase extends LitElement {
},
},
legend: {
- textStyle: {
- color: style.getPropertyValue("--primary-text-color"),
- },
+ textStyle: { color: style.getPropertyValue("--primary-text-color") },
inactiveColor: style.getPropertyValue("--disabled-text-color"),
pageIconColor: style.getPropertyValue("--primary-text-color"),
pageIconInactiveColor: style.getPropertyValue("--disabled-text-color"),
@@ -578,12 +562,8 @@ export class HaChartBase extends LitElement {
fontSize: 12,
},
axisPointer: {
- lineStyle: {
- color: style.getPropertyValue("--divider-color"),
- },
- crossStyle: {
- color: style.getPropertyValue("--divider-color"),
- },
+ lineStyle: { color: style.getPropertyValue("--divider-color") },
+ crossStyle: { color: style.getPropertyValue("--divider-color") },
},
},
timeline: {},
@@ -609,7 +589,7 @@ export class HaChartBase extends LitElement {
}
if (!this._originalZrFlush) {
const dataSize = ensureArray(this.data).reduce(
- (acc, series) => acc + (series.data as any[]).length,
+ (acc, series) => acc + ((series.data as any[]) || []).length,
0
);
if (dataSize > 10000) {
@@ -628,6 +608,23 @@ export class HaChartBase extends LitElement {
this.chart.setOption(options, { replaceMerge });
}
+ private _handleClickZoom = (e: ECElementEvent) => {
+ if (!this.chart) {
+ return;
+ }
+ const range = this._isZoomed
+ ? [0, 100]
+ : [
+ (e.offsetX / this.chart.getWidth()) * 100 - 15,
+ (e.offsetX / this.chart.getWidth()) * 100 + 15,
+ ];
+ this.chart.dispatchAction({
+ type: "dataZoom",
+ start: range[0],
+ end: range[1],
+ });
+ };
+
private _handleZoomReset() {
this.chart?.dispatchAction({ type: "dataZoom", start: 0, end: 100 });
}
diff --git a/src/resources/echarts.ts b/src/resources/echarts.ts
index 77a328722f..2f5c27e483 100644
--- a/src/resources/echarts.ts
+++ b/src/resources/echarts.ts
@@ -13,6 +13,7 @@ import {
GridComponent,
DataZoomComponent,
VisualMapComponent,
+ ToolboxComponent,
} from "echarts/components";
// Features like Universal Transition and Label Layout
@@ -69,6 +70,7 @@ echarts.use([
LabelLayout,
UniversalTransition,
CanvasRenderer,
+ ToolboxComponent,
]);
export default echarts;