Add needle option to ha-gauge and gauge card (#9637)

This commit is contained in:
Thomas Lovén 2021-07-30 10:51:21 +02:00 committed by GitHub
parent a4f51b0cb3
commit 03080973be
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 112 additions and 13 deletions

View File

@ -13,6 +13,11 @@ const getAngle = (value: number, min: number, max: number) => {
return (percentage * 180) / 100;
};
interface LevelDefinition {
level: number;
stroke: string;
}
@customElement("ha-gauge")
export class Gauge extends LitElement {
@property({ type: Number }) public min = 0;
@ -23,6 +28,10 @@ export class Gauge extends LitElement {
@property() public locale!: FrontendLocaleData;
@property({ type: Boolean }) public needle?: boolean;
@property() public levels?: LevelDefinition[];
@property() public label = "";
@state() private _angle = 0;
@ -55,18 +64,53 @@ export class Gauge extends LitElement {
class="dial"
d="M 10 50 A 40 40 0 0 1 90 50"
></path>
<path
class="value"
d="M 90 50.001 A 40 40 0 0 1 10 50"
style=${ifDefined(
!isSafari
? styleMap({ transform: `rotate(${this._angle}deg)` })
: undefined
)}
transform=${ifDefined(
isSafari ? `rotate(${this._angle} 50 50)` : undefined
)}
>
${
this.levels
? this.levels
.sort((a, b) => a.level - b.level)
.map((level) => {
const angle = getAngle(level.level, this.min, this.max);
return svg`<path
stroke="${level.stroke}"
class="level"
d="M
${50 - 40 * Math.cos((angle * Math.PI) / 180)}
${50 - 40 * Math.sin((angle * Math.PI) / 180)}
A 40 40 0 0 1 90 50
"
></path>`;
})
: ""
}
${
this.needle
? svg`<path
class="needle"
d="M 25 47.5 L 2.5 50 L 25 52.5 z"
style=${ifDefined(
!isSafari
? styleMap({ transform: `rotate(${this._angle}deg)` })
: undefined
)}
transform=${ifDefined(
isSafari ? `rotate(${this._angle} 50 50)` : undefined
)}
>
`
: svg`<path
class="value"
d="M 90 50.001 A 40 40 0 0 1 10 50"
style=${ifDefined(
!isSafari
? styleMap({ transform: `rotate(${this._angle}deg)` })
: undefined
)}
transform=${ifDefined(
isSafari ? `rotate(${this._angle} 50 50)` : undefined
)}
>`
}
${
// Workaround for https://github.com/home-assistant/frontend/issues/6467
isSafari
@ -117,6 +161,15 @@ export class Gauge extends LitElement {
transform-origin: 50% 100%;
transition: all 1s ease 0s;
}
.needle {
fill: var(--primary-text-color);
transform-origin: 50% 100%;
transition: all 1s ease 0s;
}
.level {
fill: none;
stroke-width: 15;
}
.gauge {
display: block;
}

View File

@ -135,6 +135,8 @@ class HuiGaugeCard extends LitElement implements LovelaceCard {
style=${styleMap({
"--gauge-color": this._computeSeverity(entityState),
})}
.needle=${this._config!.needle}
.levels=${this._config!.needle ? this._severityLevels() : undefined}
></ha-gauge>
<div class="name">
${this._config.name || computeStateName(stateObj)}
@ -200,6 +202,20 @@ class HuiGaugeCard extends LitElement implements LovelaceCard {
return severityMap.normal;
}
private _severityLevels() {
const sections = this._config!.severity;
if (!sections) {
return [];
}
const sectionsArray = Object.keys(sections);
return sectionsArray.map((severity) => ({
level: sections[severity],
stroke: severityMap[severity],
}));
}
private _handleClick(): void {
fireEvent(this, "hass-more-info", { entityId: this._config!.entity });
}

View File

@ -164,6 +164,7 @@ export interface GaugeCardConfig extends LovelaceCardConfig {
max?: number;
severity?: SeverityConfig;
theme?: string;
needle?: boolean;
}
export interface ConfigEntity extends EntityConfig {

View File

@ -1,7 +1,7 @@
import "@polymer/paper-input/paper-input";
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
import { customElement, property, state } from "lit/decorators";
import { assert, number, object, optional, string } from "superstruct";
import { assert, boolean, number, object, optional, string } from "superstruct";
import { fireEvent } from "../../../../common/dom/fire_event";
import { computeRTLDirection } from "../../../../common/util/compute_rtl";
import "../../../../components/ha-formfield";
@ -23,6 +23,7 @@ const cardConfigStruct = object({
max: optional(number()),
severity: optional(object()),
theme: optional(string()),
needle: optional(boolean()),
});
const includeDomains = ["counter", "input_number", "number", "sensor"];
@ -137,6 +138,17 @@ export class HuiGaugeCardEditor
.configValue=${"max"}
@value-changed="${this._valueChanged}"
></paper-input>
<ha-formfield
.label=${this.hass.localize(
"ui.panel.lovelace.editor.card.gauge.needle_gauge"
)}
.dir=${computeRTLDirection(this.hass)}
>
<ha-switch
.checked="${this._config!.needle !== undefined}"
@change="${this._toggleNeedle}"
></ha-switch
></ha-formfield>
<ha-formfield
.label=${this.hass.localize(
"ui.panel.lovelace.editor.card.gauge.severity.define"
@ -212,6 +224,22 @@ export class HuiGaugeCardEditor
];
}
private _toggleNeedle(ev: EntitiesEditorEvent): void {
if (!this._config || !this.hass) {
return;
}
if ((ev.target as EditorTarget).checked) {
this._config = {
...this._config,
needle: true,
};
} else {
this._config = { ...this._config };
delete this._config.needle;
}
fireEvent(this, "config-changed", { config: this._config });
}
private _toggleSeverity(ev: EntitiesEditorEvent): void {
if (!this._config || !this.hass) {
return;

View File

@ -3095,6 +3095,7 @@
},
"gauge": {
"name": "Gauge",
"needle_gauge": "Display as needle gauge?",
"severity": {
"define": "Define Severity?",
"green": "Green",