Backgrounds

Contour

A topographic map of terrain that will not hold still. The lines are not drawn, they are found — a height field is sampled onto a grid every frame and marching squares walks it once per altitude, emitting segments wherever the land crosses that height. Nothing here knows what a ridge is; ridges are where the crossings bunch up. The pointer raises a hill the contours have to route around, and because the interval is fixed rather than the line count, that extra altitude produces extra rings instead of restretching the ones already on screen.

Install

# Contour needs no npm packages

Then copy 2 files into your project:

  • components/registry/contour/contour.tsx
  • hooks/use-animation-loop.ts

Props

PropTypeDefaultDescription
levelsnumber22Contours per unit of altitude — the map's contour interval, inverted into the number a reader actually wants. This is a density rather than a count: how many lines land on screen is whatever that interval yields across the range the terrain currently occupies, so raising a peak under the cursor adds rings instead of crowding the ones already drawn.
cellSizenumber14Spacing of the height samples, and therefore the resolution of the whole map. Contours can only turn at a cell boundary, so a coarse grid gives visibly faceted rings while a fine one costs another full field sweep every frame. Below about 10px on a wide canvas a cost cap takes over and the cell grows back on its own.
speednumber0.6How fast the land drifts beneath the frame. It is scrolled, never regenerated — the same hills pass through and leave, which is why a feature holds its shape long enough to be recognised on the way out.
warpnumber0.35Domain warp: the sample coordinates are displaced by the field itself before it is read. At zero the map is concentric ovals and reads as a lava lamp. Raising it folds the contours into ridges, valleys and saddles, which is the point at which it starts to look surveyed rather than generated.
cursorRadiusnumber180Width of the landform the pointer raises, as the sigma of a Gaussian. Small and sharp reads as a volcanic plug with rings stacked tight around it; wide and low reads as a swell the contours merely lean around.
cursorStrengthnumber0.55Height of that landform, in the same units as the terrain. Negative digs a depression instead and the map reads as a crater rather than a hill. Zero takes the pointer off the map entirely.
indexEverynumber5Every Nth contour is an index contour, drawn brighter and heavier the way a real map weights its counted lines. The emphasis is keyed to absolute altitude rather than to draw order, so a given ring keeps its weight as the land moves under it instead of the highlight crawling through the set.
lineWidthnumber1Weight of an ordinary contour. Index contours are always drawn at one and a half times this, so the hierarchy survives at any setting.
lineColorstring (hex)"#5b5772"The ordinary contours. Deliberately close to the paper — they are the texture, not the subject.
indexColorstring (hex)"#a855f7"The index contours, and the only real light on the map.
backgroundstring (hex)"#0d0d12"The paper.

What It Demonstrates

Loop
An animation that repeats, a set number of times or infinitely.
Idle animation
Subtle motion that plays while an element is just sitting there, waiting to be interacted with.
Hover effect
Visual change when the cursor moves over an element.
Linear
Constant speed. Avoid for UI; reserve for spinners or marquees.

Related Components

Appears In