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

View File

@ -135,6 +135,8 @@ class HuiGaugeCard extends LitElement implements LovelaceCard {
style=${styleMap({ style=${styleMap({
"--gauge-color": this._computeSeverity(entityState), "--gauge-color": this._computeSeverity(entityState),
})} })}
.needle=${this._config!.needle}
.levels=${this._config!.needle ? this._severityLevels() : undefined}
></ha-gauge> ></ha-gauge>
<div class="name"> <div class="name">
${this._config.name || computeStateName(stateObj)} ${this._config.name || computeStateName(stateObj)}
@ -200,6 +202,20 @@ class HuiGaugeCard extends LitElement implements LovelaceCard {
return severityMap.normal; 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 { private _handleClick(): void {
fireEvent(this, "hass-more-info", { entityId: this._config!.entity }); fireEvent(this, "hass-more-info", { entityId: this._config!.entity });
} }

View File

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

View File

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

View File

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