Echarts: auto scale Y in log charts (#23994)

* Echarts: auto scale Y in log charts

* fix statistics chart log scale
This commit is contained in:
Petar Petrov 2025-01-31 18:42:51 +02:00 committed by Bram Kragten
parent 3769f8c7c0
commit 2fcb64d4a1
2 changed files with 66 additions and 21 deletions

View File

@ -187,11 +187,24 @@ export class StateHistoryChartLine extends LitElement {
) {
const dayDifference = differenceInDays(this.endTime, this.startTime);
const rtl = computeRTL(this.hass);
const minYAxis =
// log(0) is -Infinity, so we need to set a minimum value
this.logarithmicScale && typeof this.minYAxis === "number"
? Math.max(this.minYAxis, 0.1)
: this.minYAxis;
let minYAxis: number | ((values: { min: number }) => number) | undefined =
this.minYAxis;
let maxYAxis: number | ((values: { max: number }) => number) | undefined =
this.maxYAxis;
if (typeof minYAxis === "number") {
if (this.fitYData) {
minYAxis = ({ min }) => Math.min(min, this.minYAxis!);
}
} else if (this.logarithmicScale) {
minYAxis = ({ min }) => (min > 0 ? min * 0.95 : min * 1.05);
}
if (typeof maxYAxis === "number") {
if (this.fitYData) {
maxYAxis = ({ max }) => Math.max(max, this.maxYAxis!);
}
} else if (this.logarithmicScale) {
maxYAxis = ({ max }) => (max > 0 ? max * 1.05 : max * 0.95);
}
this._chartOptions = {
xAxis: {
type: "time",
@ -218,14 +231,8 @@ export class StateHistoryChartLine extends LitElement {
yAxis: {
type: this.logarithmicScale ? "log" : "value",
name: this.unit,
min:
this.fitYData && typeof minYAxis === "number"
? ({ min }) => Math.min(min, minYAxis!)
: minYAxis,
max:
this.fitYData && typeof this.maxYAxis === "number"
? ({ max }) => Math.max(max, this.maxYAxis!)
: this.maxYAxis,
min: this._clampYAxis(minYAxis),
max: this._clampYAxis(maxYAxis),
position: rtl ? "right" : "left",
scale: true,
nameGap: 2,
@ -644,6 +651,19 @@ export class StateHistoryChartLine extends LitElement {
this._entityIds = entityIds;
this._datasetToDataIndex = datasetToDataIndex;
}
private _clampYAxis(value?: number | ((values: any) => number)) {
if (this.logarithmicScale) {
// log(0) is -Infinity, so we need to set a minimum value
if (typeof value === "number") {
return Math.max(value, 0.1);
}
if (typeof value === "function") {
return (values: any) => Math.max(value(values), 0.1);
}
}
return value;
}
}
customElements.define("state-history-chart-line", StateHistoryChartLine);

View File

@ -218,6 +218,24 @@ export class StatisticsChart extends LitElement {
private _createOptions() {
const splitLineStyle = this.hass.themes?.darkMode ? { opacity: 0.15 } : {};
const dayDifference = this.daysToShow ?? 1;
let minYAxis: number | ((values: { min: number }) => number) | undefined =
this.minYAxis;
let maxYAxis: number | ((values: { max: number }) => number) | undefined =
this.maxYAxis;
if (typeof minYAxis === "number") {
if (this.fitYData) {
minYAxis = ({ min }) => Math.min(min, this.minYAxis!);
}
} else if (this.logarithmicScale) {
minYAxis = ({ min }) => (min > 0 ? min * 0.95 : min * 1.05);
}
if (typeof maxYAxis === "number") {
if (this.fitYData) {
maxYAxis = ({ max }) => Math.max(max, this.maxYAxis!);
}
} else if (this.logarithmicScale) {
maxYAxis = ({ max }) => (max > 0 ? max * 1.05 : max * 0.95);
}
this._chartOptions = {
xAxis: {
type: "time",
@ -252,14 +270,8 @@ export class StatisticsChart extends LitElement {
position: computeRTL(this.hass) ? "right" : "left",
// @ts-ignore
scale: true,
min:
this.fitYData && typeof this.minYAxis === "number"
? ({ min }) => Math.min(min, this.minYAxis!)
: this.minYAxis,
max:
this.fitYData && typeof this.maxYAxis === "number"
? ({ max }) => Math.max(max, this.maxYAxis!)
: this.maxYAxis,
min: this._clampYAxis(minYAxis),
max: this._clampYAxis(maxYAxis),
splitLine: {
show: true,
lineStyle: splitLineStyle,
@ -556,6 +568,19 @@ export class StatisticsChart extends LitElement {
return val;
}
private _clampYAxis(value?: number | ((values: any) => number)) {
if (this.logarithmicScale) {
// log(0) is -Infinity, so we need to set a minimum value
if (typeof value === "number") {
return Math.max(value, 0.1);
}
if (typeof value === "function") {
return (values: any) => Math.max(value(values), 0.1);
}
}
return value;
}
static styles = css`
:host {
display: block;