Skip to the page
TACTILE UI

How the Pin Screen works

The Pin Screen is the pin-art toy as a surface for a web page. A word stands in polished pins under one raking lamp. Press or drag and the pins sink under your pointer; shake it and the board goes flat, then the word pushes itself back up through the pins. This page is how.

Written 29 September 2026. Vanilla ES modules and canvas 2D, no dependencies, 18.0 KB gzipped, 23 tests. No image ships: the relief is drawn from text in the page's own fonts, a shape, or any image you pass in.

Pins on a real grid

The real toy packs its pins close, in a hex grid: each row is √3/2 of a pitch below the last, odd rows shift half a pitch, and every pin is one pitch from all six neighbours. Mine uses the same grid, with whole pins only and the grid centred, so there's never half a pin at an edge. On a small screen the pitch shrinks until a letter's stroke still spans enough pins, so a word on a phone gets finer pins instead of turning to mush.

A heightfield with memory

Each pin is on its own spring. It springs toward a target made of two things:

  • the relief, which it keeps, the way the real toy keeps its shape;
  • a pressure field that your pointer paints: lifting pins where it passes, or pressing them flat in wipe mode.

Pressure fades with a half-life, so a stroke lingers and lets go. In impression mode it stays until reset(), which drops every pin top to bottom in 0.3 seconds, then presses the relief back up from behind.

A relief from anything drawable

Text, a procedural hand, or any image is drawn once at four samples per pin and averaged into a heightmap. A plain silhouette would come out flat, like a cookie cutter, so a silhouette is inflated by its distance from its own edge: a hand comes out rounded, fingertips lower than the palm.

Light that agrees with itself

There's one lamp, low and raking.

  • A raised pin lifts its head up the screen on a visible shaft.
  • It casts a shadow away from the lamp, across the pins below it.
  • It's shadowed itself by any taller pin between it and the lamp, found by a short march through the field.

Heads, shafts, holes and shadows are drawn once into sprites. A frame is then four drawImage calls per raised pin and one blit for everything flush, and only the regions that changed are repainted.

Cost and access

  • The loop sleeps once every pin has settled, pauses while the board is off screen, and a tab coming back after two seconds can't blow up a spring.
  • It's decorative, so it's one role="img" with a text alternative, and the canvas is hidden from assistive technology.
  • With reduced motion the relief stands still on the first paint: the word stays, only the motion goes.
  • On touch it uses touch-action: pan-y, so a vertical swipe still scrolls the page.

Play with it on the object page. The source comes with a Pass.