Cursor Puck
A weighted puck on a short spring, under the pointer. It never sits where the pointer is: it lags behind, then catches up, with a coiled spring, not a dotted line, showing the stretch and compression.
What it is for
Give a hero, a cursor trail or a playful corner of a page a pointer that behaves like it has real weight on the end of a leash: a disc on a 2D mass-spring-damper, tied to wherever the pointer is, that lags when the pointer moves fast and settles once it stops.
Everything you set here is what the Code and Prompt tabs give you.
Datasheet
- Mechanism
- Mass spring damper, Fixed substep integration, Pointer or keyboard target, Rest position recentre, Sleeping loop, Reduced motion snap
- Stack
- Vanilla ES modules, CSS, SVG
- Needs
- Nothing, no dependencies
- States
- 6 documented
- Version
- 0.1.0
- Licence
- With a Pass
States
- At restThe puck sits still at the centre of its stage; the loop is asleep and costs nothing.
- Following the pointerThe pointer's own mark jumps to the cursor at once; the puck is pulled toward it by the spring and lags behind, closing the gap as the pointer slows or stops. How quickly it catches up and whether it overshoots on the way are both controls.
- Pointer leavesThe free end returns to the stage's centre; the puck catches up there over the same spring, and the loop sleeps once it is still.
- KeyboardThe stage takes focus. Arrow keys move the free end 14px at a time (Shift for 48px steps), clamped to the stage, so the lag and the catch-up are reachable without a pointer.
- Off screen or hidden tabThe loop stops requesting frames; a returning tab cannot fling the spring with a long frame, because the frame gap is clamped before it is sub-stepped.
- Reduced motionThe puck sits on the free end at every change; nothing is stepped and no frame is requested.
Notes
A coiled spring between the pointer's own mark and the puck makes the stretch and compression visible rather than implied, and the puck itself is turned, with lathe rings, a knurled rim and a cast shadow, so it reads as a real weight, not a flat disc. The same free end is reachable from the keyboard, so the lag is never pointer-only.
Original. A fixed 1/120 s sub-stepped 2D mass-spring-damper; no canvas or WebGL, the puck and its coiled spring are plain DOM (an SVG path) moved with transform. No colour of its own: the stage is the page's own panel tokens (--tui-face), the puck's turned face, lathe rings and knurled rim are the page's own object tokens (--tui-obj-body, --tui-obj-lite, --tui-obj-dark, --tui-obj-spec, --tui-obj-edge, --tui-obj-frame), the pointer's own mark is --tui-ink-3 and the coil and the cast shadow are --tui-sh, so all four finishes are correct for free.
Anatomy
Mass spring damper, Fixed substep integration, Pointer or keyboard target, Rest position recentre, Sleeping loop, Reduced motion snap
Usage notes
Give a hero, a cursor trail or a playful corner of a page a pointer that behaves like it has real weight on the end of a leash: a disc on a 2D mass-spring-damper, tied to wherever the pointer is, that lags when the pointer moves fast and settles once it stops. A coiled spring between the pointer's own mark and the puck makes the stretch and compression visible rather than implied, and the puck itself is turned, with lathe rings, a knurled rim and a cast shadow, so it reads as a real weight, not a flat disc. The same free end is reachable from the keyboard, so the lag is never pointer-only.
Options
| Option | Type | Description |
|---|---|---|
| size | number | The diameter of the weighted disc. |
| stiffness | number | How quickly the spring pulls the puck toward the pointer. Low is a slow, heavy puck; high is quick and light. |
| damping | number | Below 1 the puck overshoots and swings before it settles; 1 catches up with no overshoot; above 1 is slow and heavy. |
| tether | boolean | A coiled spring drawn between the pointer's own mark and the puck, so its stretch and compression are visible, not a dotted line. |
| label | text | Read by a screen reader before the keyboard instructions. Empty uses the default. |
Methods
- update
- state
- stats
- destroy
How it works
Original. No colour of its own.