From dddee87de37fcd6751523d4a8338cd07d1cf9c9a Mon Sep 17 00:00:00 2001 From: Paul Bottein Date: Mon, 21 Aug 2023 13:03:20 +0200 Subject: [PATCH] Use gradient based on min/max color temp for tile card feature (#17612) --- src/common/color/convert-light-color.ts | 4 +- src/components/ha-temp-color-picker.ts | 12 +++-- .../lights/light-color-temp-picker.ts | 13 ++++- .../hui-light-color-temp-tile-feature.ts | 49 +++++++++++++++++-- 4 files changed, 65 insertions(+), 13 deletions(-) diff --git a/src/common/color/convert-light-color.ts b/src/common/color/convert-light-color.ts index 3e67b00fcb..3ca78f6c5c 100644 --- a/src/common/color/convert-light-color.ts +++ b/src/common/color/convert-light-color.ts @@ -1,7 +1,7 @@ import { clamp } from "../number/clamp"; -const DEFAULT_MIN_KELVIN = 2700; -const DEFAULT_MAX_KELVIN = 6500; +export const DEFAULT_MIN_KELVIN = 2700; +export const DEFAULT_MAX_KELVIN = 6500; export const temperature2rgb = ( temperature: number diff --git a/src/components/ha-temp-color-picker.ts b/src/components/ha-temp-color-picker.ts index 4e0d109109..ce471c207f 100644 --- a/src/components/ha-temp-color-picker.ts +++ b/src/components/ha-temp-color-picker.ts @@ -1,10 +1,14 @@ import { DIRECTION_ALL, Manager, Pan, Tap } from "@egjs/hammerjs"; -import { css, html, LitElement, PropertyValues, svg } from "lit"; +import { LitElement, PropertyValues, css, html, svg } from "lit"; import { customElement, property, query, state } from "lit/decorators"; import { classMap } from "lit/directives/class-map"; import { styleMap } from "lit/directives/style-map"; import { rgb2hex } from "../common/color/convert-color"; -import { temperature2rgb } from "../common/color/convert-light-color"; +import { + DEFAULT_MAX_KELVIN, + DEFAULT_MIN_KELVIN, + temperature2rgb, +} from "../common/color/convert-light-color"; import { fireEvent } from "../common/dom/fire_event"; const SAFE_ZONE_FACTOR = 0.9; @@ -79,10 +83,10 @@ class HaTempColorPicker extends LitElement { public value?: number; @property({ type: Number }) - public min = 2000; + public min = DEFAULT_MIN_KELVIN; @property({ type: Number }) - public max = 10000; + public max = DEFAULT_MAX_KELVIN; @query("#canvas") private _canvas!: HTMLCanvasElement; diff --git a/src/dialogs/more-info/components/lights/light-color-temp-picker.ts b/src/dialogs/more-info/components/lights/light-color-temp-picker.ts index 4543c0dc88..cd69b7ba7d 100644 --- a/src/dialogs/more-info/components/lights/light-color-temp-picker.ts +++ b/src/dialogs/more-info/components/lights/light-color-temp-picker.ts @@ -16,6 +16,10 @@ import { LightEntity, } from "../../../../data/light"; import { HomeAssistant } from "../../../../types"; +import { + DEFAULT_MAX_KELVIN, + DEFAULT_MIN_KELVIN, +} from "../../../../common/color/convert-light-color"; declare global { interface HASSDomEvents { @@ -37,12 +41,17 @@ class LightColorTempPicker extends LitElement { return nothing; } + const minKelvin = + this.stateObj.attributes.min_color_temp_kelvin ?? DEFAULT_MIN_KELVIN; + const maxKelvin = + this.stateObj.attributes.max_color_temp_kelvin ?? DEFAULT_MAX_KELVIN; + return html` diff --git a/src/panels/lovelace/tile-features/hui-light-color-temp-tile-feature.ts b/src/panels/lovelace/tile-features/hui-light-color-temp-tile-feature.ts index 78fbab6367..43f16a4655 100644 --- a/src/panels/lovelace/tile-features/hui-light-color-temp-tile-feature.ts +++ b/src/panels/lovelace/tile-features/hui-light-color-temp-tile-feature.ts @@ -1,6 +1,14 @@ import { HassEntity } from "home-assistant-js-websocket"; import { css, html, LitElement, nothing } from "lit"; import { customElement, property, state } from "lit/decorators"; +import { styleMap } from "lit/directives/style-map"; +import memoizeOne from "memoize-one"; +import { rgb2hex } from "../../../common/color/convert-color"; +import { + DEFAULT_MAX_KELVIN, + DEFAULT_MIN_KELVIN, + temperature2rgb, +} from "../../../common/color/convert-light-color"; import { computeDomain } from "../../../common/entity/compute_domain"; import { stateActive } from "../../../common/entity/state_active"; import "../../../components/ha-control-slider"; @@ -57,6 +65,13 @@ class HuiLightColorTempTileFeature ? this.stateObj.attributes.color_temp_kelvin : undefined; + const minKelvin = + this.stateObj.attributes.min_color_temp_kelvin ?? DEFAULT_MIN_KELVIN; + const maxKelvin = + this.stateObj.attributes.max_color_temp_kelvin ?? DEFAULT_MAX_KELVIN; + + const gradient = this.generateTemperatureGradient(minKelvin!, maxKelvin); + return html`
`; } + private generateTemperatureGradient = memoizeOne( + (min: number, max: number) => { + const count = 10; + + const gradient: [number, string][] = []; + + const step = (max - min) / count; + const percentageStep = 1 / count; + + for (let i = 0; i < count + 1; i++) { + const value = min + step * i; + + const hex = rgb2hex(temperature2rgb(value)); + gradient.push([percentageStep * i, hex]); + } + + return gradient + .map(([stop, color]) => `${color} ${(stop as number) * 100}%`) + .join(", "); + } + ); + private _valueChanged(ev: CustomEvent) { ev.stopPropagation(); const value = ev.detail.value; @@ -86,11 +126,10 @@ class HuiLightColorTempTileFeature static get styles() { return css` ha-control-slider { + --control-slider-color: var(--tile-color); --control-slider-background: -webkit-linear-gradient( left, - rgb(255, 160, 0) 0%, - white 50%, - rgb(166, 209, 255) 100% + var(--gradient) ); --control-slider-background-opacity: 1; --control-slider-thickness: 40px;