Slow every animation down for a low-res screen
Every speed in config.js is in pixels per second, so the same numbers cross a small screen in less time than a big one: on 1280x800 the frame covers the width in two thirds of the time it takes on 1920x1080, and the player reads as hurried. One factor now sits behind every animation clock — tickSeconds() for the frame loops, `speed` for the corners timer, and a --motion-stretch custom property for the two CSS fades — so the Speed switch on the queue page slows the drift, the glides, the pong rally, the drag beats, the wash lap, the screenshot intervals and the fades together. It is read per frame rather than baked into the constants, so flipping the switch lands on the next frame: no animation restarts, and one part-way through a beat keeps its place. The trail's stills now age on animation time rather than wall-clock time, so a still fades at the rate the frame that dropped it is moving. The audio crossfade is deliberately left out, being tied to the track that is ending. The flag is saved with the queue, unlike `paused`: it describes the screen the player is on, which a restart does not change. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011vCaS2whbFjExShoPNnS3A
This commit is contained in:
@@ -9,8 +9,8 @@ A YouTube playlist player for parties. Two browser windows run side by side:
|
||||
overlap in a 5 second audio/video crossfade, so there is never silence
|
||||
between tracks.
|
||||
- **Queue** (`http://localhost:3000/queue`) — add videos by URL, drag to
|
||||
reorder, delete, see how much playtime is left, and pick the background and
|
||||
animation.
|
||||
reorder, delete, see how much playtime is left, and pick the background,
|
||||
animation and animation speed.
|
||||
|
||||
## Run
|
||||
|
||||
@@ -36,7 +36,7 @@ autoplay, so the first click is what unlocks audio. One click per session.
|
||||
- The queue is saved to `queue.json` on every change and restored at startup.
|
||||
- Settings live in `config.js`: overlap length, frame size, drift speed, corner
|
||||
screenshot interval and margin, the drag animation's size range, the
|
||||
background zoom range, port, and the animation list. Everything there except
|
||||
background zoom range, the low-res speed factor, port, and the animation list. Everything there except
|
||||
`PORT` is mirrored to the browser by the generated `/config.js` route in
|
||||
`server/index.js`, so a new constant needs no second list.
|
||||
|
||||
@@ -93,6 +93,22 @@ today:
|
||||
a half per lap, and the frame's glow travels with it. The one still animation,
|
||||
which is what makes it worth having between the moving ones.
|
||||
|
||||
### Speed
|
||||
|
||||
Every speed in `config.js` is in pixels per second, so the same numbers cross a
|
||||
small screen in less time than a big one — on 1280x800 the frame covers the
|
||||
width in two thirds of the time it takes on 1920x1080, and the whole player
|
||||
reads as hurried. The queue page's **Speed** switch fixes that: **Low-res
|
||||
screen** multiplies every animation clock by `LOW_RES_SPEED` (0.65, the
|
||||
1280/1920 ratio), which slows the drift, the glides, the pong rally, the drag
|
||||
beats, the wash lap, the screenshot intervals and the fades together.
|
||||
|
||||
It is one factor read per frame rather than a set of slower constants, so
|
||||
flipping the switch takes effect on the next frame — no animation restarts, and
|
||||
one part-way through a beat keeps its place. The audio crossfade is deliberately
|
||||
left out: it is tied to the track that is ending. The setting is saved with the
|
||||
queue, since it describes the screen the player is on.
|
||||
|
||||
The queue page's **Animation** buttons pin the player to one of them, which is
|
||||
how you look at a single animation without waiting for the cycle to reach it.
|
||||
**Auto** (the default) hands selection back to the shuffle bag. Switching takes
|
||||
@@ -161,6 +177,12 @@ the same element immediately. Register it under a new name in the `ANIMATIONS`
|
||||
map in `motion.js` **and** in the one in `config.js` (which supplies the label
|
||||
for the queue page's button), and it joins the rotation.
|
||||
|
||||
Anything time-driven should take its seconds from `tickSeconds(now, last)`
|
||||
rather than from the raw timestamps, and any timer should divide its interval by
|
||||
`speed`. That is what puts a new animation under the **Speed** switch — and the
|
||||
clamp inside it is also what stops a hidden tab from teleporting the frame when
|
||||
it comes back.
|
||||
|
||||
Selection uses a shuffle bag (`createPicker`): every animation comes up exactly
|
||||
once per pass, so they stay evenly used, and the same one never runs twice in a
|
||||
row — including across the seam between two passes.
|
||||
|
||||
Reference in New Issue
Block a user