diff --git a/gallery/src/pages/components/ha-control-circular-slider.ts b/gallery/src/pages/components/ha-control-circular-slider.ts
index 8c6fca52d4..f85f210dd0 100644
--- a/gallery/src/pages/components/ha-control-circular-slider.ts
+++ b/gallery/src/pages/components/ha-control-circular-slider.ts
@@ -150,17 +150,13 @@ export class DemoHaCircularSlider extends LitElement {
}
ha-control-circular-slider {
--control-circular-slider-color: #ff9800;
- --control-circular-slider-background: #ff9800;
- --control-circular-slider-background-opacity: 0.3;
}
ha-control-circular-slider[inverted] {
--control-circular-slider-color: #2196f3;
- --control-circular-slider-background: #2196f3;
}
ha-control-circular-slider[dual] {
--control-circular-slider-high-color: #2196f3;
--control-circular-slider-low-color: #ff9800;
- --control-circular-slider-background: var(--disabled-color);
}
.field {
display: flex;
diff --git a/src/components/ha-control-circular-slider.ts b/src/components/ha-control-circular-slider.ts
index 5b3caf3bef..ffe26f17dc 100644
--- a/src/components/ha-control-circular-slider.ts
+++ b/src/components/ha-control-circular-slider.ts
@@ -18,10 +18,9 @@ import {
import { customElement, property, query, state } from "lit/decorators";
import { classMap } from "lit/directives/class-map";
import { ifDefined } from "lit/directives/if-defined";
-import { styleMap } from "lit/directives/style-map";
import { fireEvent } from "../common/dom/fire_event";
import { clamp } from "../common/number/clamp";
-import { arc } from "../resources/svg-arc";
+import { svgArc } from "../resources/svg-arc";
const MAX_ANGLE = 270;
const ROTATE_ANGLE = 360 - MAX_ANGLE / 2 - 90;
@@ -388,44 +387,130 @@ export class HaControlCircularSlider extends LitElement {
}
}
- private _strokeDashArc(
- percentage: number,
- inverted?: boolean
- ): [string, string] {
- const maxRatio = MAX_ANGLE / 360;
- const f = RADIUS * 2 * Math.PI;
- if (inverted) {
- const arcLength = (1 - percentage) * f * maxRatio;
- const strokeDasharray = `${arcLength} ${f - arcLength}`;
- const strokeDashOffset = `${arcLength + f * (1 - maxRatio)}`;
- return [strokeDasharray, strokeDashOffset];
- }
- const arcLength = percentage * f * maxRatio;
- const strokeDasharray = `${arcLength} ${f - arcLength}`;
- const strokeDashOffset = "0";
+ private _strokeCircleDashArc(value: number): [string, string] {
+ return this._strokeDashArc(value, value);
+ }
+
+ private _strokeDashArc(from: number, to: number): [string, string] {
+ const start = this._valueToPercentage(from);
+ const end = this._valueToPercentage(to);
+
+ const track = (RADIUS * 2 * Math.PI * MAX_ANGLE) / 360;
+ const arc = Math.max((end - start) * track, 0);
+ const arcOffset = start * track - 0.5;
+
+ const strokeDasharray = `${arc} ${track - arc}`;
+ const strokeDashOffset = `-${arcOffset}`;
return [strokeDasharray, strokeDashOffset];
}
+ protected renderArc(
+ id: string,
+ value: number | undefined,
+ inverted: boolean | undefined
+ ) {
+ const limit = inverted ? this.max : this.min;
+
+ const path = svgArc({
+ x: 0,
+ y: 0,
+ start: 0,
+ end: MAX_ANGLE,
+ r: RADIUS,
+ });
+
+ const current = this.current ?? limit;
+ const target = value ?? limit;
+
+ const showActive = inverted ? target <= current : current <= target;
+
+ const activeArcDashArray = showActive
+ ? inverted
+ ? this._strokeDashArc(target, current)
+ : this._strokeDashArc(current, target)
+ : this._strokeCircleDashArc(target);
+
+ const arcDashArray = inverted
+ ? this._strokeDashArc(target, limit)
+ : this._strokeDashArc(limit, target);
+
+ const targetCircleDashArray = this._strokeCircleDashArc(target);
+
+ const currentCircleDashArray =
+ this.current != null && showActive
+ ? this._strokeCircleDashArc(this.current)
+ : undefined;
+
+ return svg`
+
+
+
+
+ ${
+ currentCircleDashArray
+ ? svg`
+
+ `
+ : nothing
+ }
+ `;
+ }
+
protected render(): TemplateResult {
- const trackPath = arc({ x: 0, y: 0, start: 0, end: MAX_ANGLE, r: RADIUS });
+ const trackPath = svgArc({
+ x: 0,
+ y: 0,
+ start: 0,
+ end: MAX_ANGLE,
+ r: RADIUS,
+ });
const lowValue = this.dual ? this._localLow : this._localValue;
const highValue = this._localHigh;
- const lowPercentage = this._valueToPercentage(lowValue ?? this.min);
- const highPercentage = this._valueToPercentage(highValue ?? this.max);
+ const current = this.current;
- const [lowStrokeDasharray, lowStrokeDashOffset] = this._strokeDashArc(
- lowPercentage,
- this.inverted
- );
-
- const [highStrokeDasharray, highStrokeDashOffset] = this._strokeDashArc(
- highPercentage,
- true
- );
-
- const currentPercentage = this._valueToPercentage(this.current ?? 0);
- const currentAngle = currentPercentage * MAX_ANGLE;
+ const currentStroke = current
+ ? this._strokeCircleDashArc(current)
+ : undefined;
return html`