DIPOLE — field notes: how a magnetic field rendered in iron filings was made

DIPOLE. field notes
← View the site

A magnetic field is a rule at every point in space. DIPOLE gives that rule a body in iron — and lets you drag it around.

DIPOLE renders the invisible field of a bar magnet as roughly three thousand canvas iron filings, each short segment rotated to the field vector where it sits. Drag the magnet and the whole field re-knits in real time; summon a second bar to watch two fields attract, or flip it to see them repel and open a dead null between the poles. Built for the Generative Assets collection as a study in making an unseen force legible.

Palette

Argued from the subject: a machinist's bench, cold-rolled iron, and the one hot pole.

Bench iron
#0E1013
The dark steel bench the filings scatter on. Near-black, faintly blue, so the ember pole and cool filings both sing against it.
Filing (line/mark)
#9AA6BC
Cold-rolled iron with a blue cast. Used only for filing strokes and streamlines — never for body copy.
North-pole ember
#E0503A
The one warm mark. The N pole and its glow; filings near it warm toward this.
South-pole steel
#5B8FD6
Derived cool complement for the S pole, so polarity reads at a glance without a legend.
Body ink
#CDD4E0
A separate light cool ink for copy — ~12:1 on the bench. The filing tone would fail 4.5:1 as text.
Ink dim
#8A93A6
Secondary ink for readouts and captions, still ~6:1 on the bench.
Type
Space Grotesk
Display · wordmark · headings

A grotesque with slightly mechanical, drafted terminals — it reads like instrument lettering without tipping into novelty. Wide tracking on the wordmark makes DIPOLE feel stamped into the bench.

IBM Plex Mono
Readouts · labels · pole glyphs

Every number on the page — field strength, bearing, pole count, mode — is monospaced, so the live HUD ticks in place like a bench gaussmeter. The N/S glyphs on the magnet are Plex Mono too.

Technique

Canvas 2D vector field + filing advection

The bar magnet is modelled as two point poles of opposite magnetic charge. The field at any point is the inverse-square sum from every live pole (softened near the cores to stay finite). Each filing samples that field and eases its angle toward the local axis — filings are undirected, so the rotation wraps modulo 180°, and the easing lag is exactly what you read as the field "settling".

Beneath the filings, a soft under-layer traces continuous field-line streamlines: fifteen seeds ring each north pole and integrate along the normalised field with a midpoint step until they plunge into a south pole or leave the frame. That layer is what turns a scatter of splinters into unmistakable dipole loops — the filings visibly sit on real lines.

A coarse background scan flags field nulls — points where the vectors cancel to nothing — and marks them; they only appear when two like poles face each other in repel mode. The whole field re-solves every frame, so dragging a bar or flipping a polarity re-knits everything live. No libraries: one canvas, one requestAnimationFrame loop, DPR capped at 2, paused when the tab is hidden.

Build log

Pass 1 — Craft

The first field read as two radial starbursts, not loops: the alpha curve crushed the mid-field where the arcs live. Swapped to a gentler power curve with a raised floor so the loops stay legible, and calmed filing length so near-pole strokes stopped spiking. Caught an inverted physics label — the two-bar default showed like-poles facing (a repulsion null) yet read "ATTRACT"; corrected the polarity and the attract/repel logic. Fixed an ugly "re-knit" hyphenation in the tagline and moved the drag hint off the magnet.

Pass 2 — Depth

Added the continuous streamline under-layer — the single biggest lift, turning the scatter into readable dipole loops (the second-read "those are the actual lines" moment). Set the second bar to spawn as a clean attracting pair whose lines bridge the gap, with flip-to-repel revealing a field null. Added a micro-interaction: grabbing a bar swells its pole glow via an eased boost. Tightened the null detector so no spurious crosshair appears in the attract configuration.

Pass 3 — Hardening

Verified 375px (nav, wordmark, HUD and controls all inside the viewport, no real overflow), the reduced-motion path (a settled non-blank frame, loop fully killed), focus-visible rings, DPR cap and debounced resize, and rAF pause on tab-hide. Confirmed liveness both ways: the field animates at rest under the slow autopilot drift and re-knits on drag. Chanel rule — removed the magnet's metallic sheen overlay (shadow, body gradients, seam and labels already carry its dimension) and its now-dead helper.