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

View File

@ -218,6 +218,24 @@ export class StatisticsChart extends LitElement {
private _createOptions() { private _createOptions() {
const splitLineStyle = this.hass.themes?.darkMode ? { opacity: 0.15 } : {}; const splitLineStyle = this.hass.themes?.darkMode ? { opacity: 0.15 } : {};
const dayDifference = this.daysToShow ?? 1; 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 = { this._chartOptions = {
xAxis: { xAxis: {
type: "time", type: "time",
@ -252,14 +270,8 @@ export class StatisticsChart extends LitElement {
position: computeRTL(this.hass) ? "right" : "left", position: computeRTL(this.hass) ? "right" : "left",
// @ts-ignore // @ts-ignore
scale: true, scale: true,
min: min: this._clampYAxis(minYAxis),
this.fitYData && typeof this.minYAxis === "number" max: this._clampYAxis(maxYAxis),
? ({ min }) => Math.min(min, this.minYAxis!)
: this.minYAxis,
max:
this.fitYData && typeof this.maxYAxis === "number"
? ({ max }) => Math.max(max, this.maxYAxis!)
: this.maxYAxis,
splitLine: { splitLine: {
show: true, show: true,
lineStyle: splitLineStyle, lineStyle: splitLineStyle,
@ -556,6 +568,19 @@ export class StatisticsChart extends LitElement {
return val; 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` static styles = css`
:host { :host {
display: block; display: block;