mirror of
https://github.com/home-assistant/frontend.git
synced 2025-04-25 22:07:20 +00:00
Add needle option to ha-gauge and gauge card (#9637)
This commit is contained in:
parent
a4f51b0cb3
commit
03080973be
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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 });
|
||||||
}
|
}
|
||||||
|
@ -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 {
|
||||||
|
@ -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;
|
||||||
|
@ -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",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user