The word is drawn once to an offscreen canvas, its bitmap sampled on a grid, and every lit pixel becomes an anchor. The cursor applies an inverse-square repulsion; the springs pull everything home. All positions live in flat Float32Arrays — no objects, no allocation per frame.
Every dot is a damped spring anchored to a pixel of rendered text, scattered by an inverse-square force from your pointer. Without a pointer there is nothing to scatter it.
Below is how it is built.
Best on a desktop — bring a pointer ↗Around 5,000 independently simulated particles at 60fps, in JavaScript, on the main thread, while the rest of the page stays responsive. That is a 16ms budget shared with layout and paint.
An array of particle objects allocates on every frame and hands the garbage collector thousands of short-lived references. The result is not a low frame rate — it is periodic stalls, which read worse than consistent slowness.
Every quantity lives in a flat Float32Array — positions,
velocities, targets, per-particle seed. No objects, no allocation inside
the loop, nothing for the collector to sweep. All particles are drawn as
one batched path with a single fill, then a second pass tints only those
moving fast enough to matter.
Particles do not collide with each other. Pairwise collision is O(n²), and at this count it would need spatial hashing that buys nothing visually — the anchors already keep the field readable. Repulsion comes from a single point: your cursor.