Timing & tracks
How HyperFrames advances time with a virtual seek clock, dispatches hf-seek per frame, and drives multiple tracks in lockstep.
HyperFrames does not run a real-time clock. It runs a seek loop — for each frame, it sets the page's notion of time to frame_index / fps, lets layout settle, and captures the pixel buffer. Everything else, from CSS animations to GSAP timelines, hangs off that one event.
What you'll learn
- Why
setTimeoutandrequestAnimationFrameare stubbed at render time - How the
hf-seekevent drives JavaScript animations deterministically - How multiple tracks stay in lockstep across a single scrub
The runtime clock
When HyperFrames renders, time is a function, not a thread. For every output frame:
- The clock advances to
frame_index / fps. setTimeout,setInterval,requestAnimationFrame,Date.now(), andperformance.now()are reseeded.- A
hf-seekCustomEventis dispatched onwindow. - Styles and layout flush.
- Pixels are captured.
The whole pipeline is synchronous from the page's point of view. There is no race between your animation tick and the capture.
The hf-seek event
window.addEventListener("hf-seek", (e) => {
// e.detail.time — seconds into the composition
// e.detail.frame — frame index
// e.detail.duration — total seconds
});This is the canonical hook for any motion you can't express in pure CSS.
Four tracks, one scrubber
The demo below has four tracks — a progress bar, a number counter, a moving dot, and a rotating square. All four read from the same hf-seek event, so dragging the scrubber moves them as a unit. That's the whole timing model in one screen.
CSS animations
Pure CSS animations work out of the box. The renderer samples animation-play-state, animation-delay, and animation-duration per frame. Avoid animation-timing-function: steps() with very small step counts — the rounding can land between frames.
Third-party libraries
Most popular animation libraries have adapters in @hyperframes/adapters:
- GSAP —
gsap.tickeris pinned to HF time - Lottie / dotLottie —
goToAndStop(frame)is driven bye.detail.frame - Three.js —
AnimationMixerand aClockproxy - Rive —
advance(delta)is called per frame - Anime.js, WAAPI, D3 — covered too
See Frame adapters for the full table.
Next
- Frame adapters — pin your animation library to the seek clock
- Preview — scrub, frame-step, and reload while you author