Belts and particles
A group of states hand their body over to an overlay. The body morphs into a circle, shrinks to a core, and the meaning is carried by what orbits it — or, for two of them, by a glyph drawn beside it.
This is how the
eyesandlinefaces draw them. With the defaultcuteface the body stays whole, face included, and the same meaning is thrown beside it as an effect (rising dots forthinking, a filling arc forprogress, a pencil forwriting;powering-downdims the body andbouncinghops it). The demos below useface="eyes"so the belts themselves are visible.
The transition
beltBlend drives it. The first 62% morphs the polar ring towards a circle; the remainder shrinks that circle to the belt's core size. Eyes fade out over the first 35%, since a face on a small sphere reads as a mistake.
| belt | state | core | |
|---|---|---|---|
dots | thinking | 22 | |
orbit | orbit | 26 | |
orbit | messaging | 26 | |
orbit | waiting | 26 | |
radar | radar | 28 | |
progress | progress | 30 | |
gather | spawning | 26 | |
wave | dictating | 20 | |
send | sending | 26 | |
receive | receiving | 26 | |
dock | uploading | 26 | |
ball | bouncing | 30 | |
whirl | loading | 28 | |
standby | powering-down | 26 | |
pencil | writing | 34 | |
bang | alerting | 24 |
Each belt
The two glyphs are generated, not drawn: pencilGlyphPath and bangGlyphPath build them from a rounded rectangle, a triangle and a capsule with the same PathBuilder the bodies use. When a belt changes kind — thinking handing over to writing, say — a second spring, beltFade, cross-fades the two frames and collapses the outgoing beads into the incoming glyph's position.
Belts are pure functions of time
Nothing accumulates between calls. A belt can be paused, scrubbed, resumed or evaluated out of order and still be correct.
This is what lets hundreds of characters be frozen and thawed as they scroll in and out of view without drifting out of sync: there is no internal state to drift.
Particles
Two systems share one update.
Confetti launches evenly round a ring at the body radius, with an upward bias, then falls under gravity with per-frame damping and shrinks a little as it goes. Lifetimes are 0.45 to 0.85 seconds. Roughly one in six pieces is a gold star; the rest are dots or strips. Opacity fades in over the first tenth of the lifetime, then out on a power curve, which reads as receding rather than dissolving.
Ribbons are flung off a spin. A spin is a turn about the vertical axis: the body stays upright and the face slides round it and back. When the spin passes 5 rad/s, four to six ribbons leave one after another on two or three tilted orbit planes, inner orbits first. Each is one soft colour, spaced round the hue wheel from the others, wide at the head and half as wide at the tail. A ribbon grows in, follows the spin with a follow factor between 0.74 and 0.94, coasts once the body stops, then draws its arc back into the head and is gone.
Each ribbon is split by depth into the stretches behind the body and the stretches in front, so it passes around the character rather than across it.
The size trap
Particle scaling must not be derived from a measurement of the rendered element.
A shared animation source lives in a hidden container, and mirrors of it can be displayed at any size from 16 to 400 pixels. If the source measures its own box to decide how large particles should be, every mirror inherits the source's measurement — which is wrong for all of them, and pathologically wrong when the source is collapsed to a few pixels.
Scale is passed in explicitly instead.
Next
- Rendering structure — one SVG, every attribute written by hand
- States — every animation state, grouped