Clock: hand outlines drawn once, bubbles beside the watch
The hands' drop-shadow outline sat on their own compositor layers, so the GPU recomputed it every frame a bubble moved. It is now on an inner box, painted once into the hand's layer. The bubbles rise beside the watch, never behind it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -19,13 +19,16 @@ import { SKIN } from "../lib/skins";
|
|||||||
import { SHOW_DECORATIVE_ANIMATIONS } from "../lib/theme";
|
import { SHOW_DECORATIVE_ANIMATIONS } from "../lib/theme";
|
||||||
import { Drift, type DriftField } from "./Drift";
|
import { Drift, type DriftField } from "./Drift";
|
||||||
|
|
||||||
|
/** Beside the watch only, never behind it: on a 1080p kiosk the watch covers roughly
|
||||||
|
* 28-72% of the width, and a bubble rising behind it would drag the watch into every
|
||||||
|
* frame the Pi redraws. */
|
||||||
const BUBBLES: DriftField = [
|
const BUBBLES: DriftField = [
|
||||||
[5, 14, 0.5, 9, 0],
|
[5, 14, 0.5, 9, 0],
|
||||||
[12, 22, 0.5, 12, -3],
|
[12, 22, 0.5, 12, -3],
|
||||||
|
[17, 16, 0.5, 11, -2],
|
||||||
[22, 10, 0.5, 8, -6],
|
[22, 10, 0.5, 8, -6],
|
||||||
[48, 16, 0.5, 11, -2],
|
|
||||||
[63, 12, 0.5, 10, -7],
|
|
||||||
[78, 24, 0.5, 14, -5],
|
[78, 24, 0.5, 14, -5],
|
||||||
|
[83, 12, 0.5, 10, -7],
|
||||||
[88, 12, 0.5, 9, -1],
|
[88, 12, 0.5, 9, -1],
|
||||||
[95, 18, 0.5, 13, -9],
|
[95, 18, 0.5, 13, -9],
|
||||||
];
|
];
|
||||||
@@ -69,10 +72,14 @@ export function ClockOverlay({ visible, clock, onClose }: Props) {
|
|||||||
<div className="clock-face">
|
<div className="clock-face">
|
||||||
<Dial />
|
<Dial />
|
||||||
<div className="clock-hand clock-hand-hour" style={{ transform: `rotate(${angles.hour}deg)` }}>
|
<div className="clock-hand clock-hand-hour" style={{ transform: `rotate(${angles.hour}deg)` }}>
|
||||||
<div />
|
<div>
|
||||||
|
<div />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="clock-hand clock-hand-minute" style={{ transform: `rotate(${angles.minute}deg)` }}>
|
<div className="clock-hand clock-hand-minute" style={{ transform: `rotate(${angles.minute}deg)` }}>
|
||||||
<div />
|
<div>
|
||||||
|
<div />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="clock-hand clock-hand-second" style={{ transform: `rotate(${angles.second}deg)` }}>
|
<div className="clock-hand clock-hand-second" style={{ transform: `rotate(${angles.second}deg)` }}>
|
||||||
<div />
|
<div />
|
||||||
|
|||||||
@@ -362,8 +362,12 @@
|
|||||||
will-change: transform;
|
will-change: transform;
|
||||||
}
|
}
|
||||||
|
|
||||||
.clock-hand-hour,
|
/* The outline and shadow, on the hand's inner box rather than the hand: a filter on the
|
||||||
.clock-hand-minute {
|
layer itself would be recomputed on the GPU every frame anything on screen moves (the
|
||||||
|
bubbles), while one inside it is drawn once into the layer's picture. The shape is
|
||||||
|
one level further in, so the outline goes round the clipped arrow, not its box. */
|
||||||
|
.clock-hand-hour > div,
|
||||||
|
.clock-hand-minute > div {
|
||||||
filter: drop-shadow(0.35vmin 0 0 var(--clock-ink)) drop-shadow(-0.35vmin 0 0 var(--clock-ink))
|
filter: drop-shadow(0.35vmin 0 0 var(--clock-ink)) drop-shadow(-0.35vmin 0 0 var(--clock-ink))
|
||||||
drop-shadow(0 0.35vmin 0 var(--clock-ink)) drop-shadow(0 -0.35vmin 0 var(--clock-ink))
|
drop-shadow(0 0.35vmin 0 var(--clock-ink)) drop-shadow(0 -0.35vmin 0 var(--clock-ink))
|
||||||
drop-shadow(0 1vmin 1vmin oklch(15% 0.05 210 / 0.3));
|
drop-shadow(0 1vmin 1vmin oklch(15% 0.05 210 / 0.3));
|
||||||
@@ -382,8 +386,18 @@
|
|||||||
margin-left: -2.7vmin;
|
margin-left: -2.7vmin;
|
||||||
}
|
}
|
||||||
|
|
||||||
.clock-hand-hour > div {
|
.clock-hand-hour > div,
|
||||||
|
.clock-hand-minute > div {
|
||||||
bottom: -3.5vmin;
|
bottom: -3.5vmin;
|
||||||
|
}
|
||||||
|
|
||||||
|
.clock-hand-hour > div > div,
|
||||||
|
.clock-hand-minute > div > div {
|
||||||
|
position: absolute;
|
||||||
|
inset: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.clock-hand-hour > div > div {
|
||||||
background: oklch(92% 0.06 345);
|
background: oklch(92% 0.06 345);
|
||||||
clip-path: polygon(50% 0%, 100% 22%, 66% 22%, 66% 100%, 34% 100%, 34% 22%, 0% 22%);
|
clip-path: polygon(50% 0%, 100% 22%, 66% 22%, 66% 100%, 34% 100%, 34% 22%, 0% 22%);
|
||||||
}
|
}
|
||||||
@@ -394,8 +408,7 @@
|
|||||||
margin-left: -2.5vmin;
|
margin-left: -2.5vmin;
|
||||||
}
|
}
|
||||||
|
|
||||||
.clock-hand-minute > div {
|
.clock-hand-minute > div > div {
|
||||||
bottom: -3.5vmin;
|
|
||||||
background: oklch(92% 0.05 200);
|
background: oklch(92% 0.05 200);
|
||||||
clip-path: polygon(50% 0%, 100% 14%, 64% 14%, 64% 100%, 36% 100%, 36% 14%, 0% 14%);
|
clip-path: polygon(50% 0%, 100% 14%, 64% 14%, 64% 100%, 36% 100%, 36% 14%, 0% 14%);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user