Random
Dissecting an order that looks random
Nine dots pop in an order you can't predict — yet no random number is drawn anywhere. The motion is one keyframed clip, replayed by all nine duplicates 2 frames apart; the order comes from a single fixed table holding the numbers 0–8. The whole build — down to the spring-like undershoot that turns out to be an authored key — is dissected as one pure function.
- Published
- June 10, 2026
- Topics
- Scramble · Determinism · Easing · SVG
Try to call the next dot
Watch the loop and try to call which dot pops next. Bottom-right goes first. Then the middle of the top row, then the middle of the bottom row — it reads as scattered, yet the order is exactly the same every loop. Bottom-left pops last, and the loop hands back to bottom-right.
What looks scattered is not a random number. The motion is a single clip, and nine duplicates replay that same clip 2 frames apart. Which duplicate starts when is decided by one fixed order table — nine grid cells holding the numbers 0–8: `[[5,1,6],[7,3,4],[8,2,0]]`. That one table is the entire "random".
Build exactly one clip
- pop from the rest radius 12.02 to 26.19 in 9 frames
- drop too far, to 21.84, in 9 more — an authored undershoot
- recover to 22.39 in 7, then hold for 25 frames
- one final 18-frame ease back to the rest radius
The clip is just six radius keyframes and five easing curves, one per segment. A segment between equal values cannot move no matter what its curve says — that is how the 25-frame hold is made.
The duplicates carry no individuality. Nine dots sit fixed on a 3×3 grid about 59px apart, sharing pop size and curve shape — align all nine on their start frames and overlay them, and the spread averages just 0.07px. Only the start frame differs, and the shift measures exactly 2 frames × position in the order, for every dot.
The return after the pop lands exactly on the rest radius. The original video trails a faint tail that never quite returns to 12.02 — but the last duplicate's clip starts on frame 19 and ends on frame 87, using up nearly all 90 frames. Chasing the tail would break the loop seam. So the tail was dropped, in favor of a loop whose last frame lines up exactly with its first.
Keys, not a spring
Pop, overshoot, settle — it looks like a spring. But the best spring equation still misses by 0.252px, while the six-keyframe build misses by 0.034px — about a seventh of that. Even so, the deciding evidence is not how close the equations get. It sits at the exit of the hold.
The 25-frame hold drifts a dead-flat 0.04px. Right after it, the radius velocity steps from nearly 0 to −1.07px per frame in one jump, and the shrink back begins. A spring that keeps oscillating cannot produce that switch. The undershoot is not physics ringing out — it is a key someone placed.
One pure function is all you need
The implementation is one pure function: pass a frame number, get back nine centres and radii. The order table is plain data handed to the function — no shuffle, no random seed; the same frame always returns the same pose. The keyframes, easing curves, grid coordinates and the table sit as plain constants in the JavaScript this page loads: the browser's view-source doubles as the spec sheet.