← return to Black Fell MAKING NOTES / 16

The Slow Survey

A field that
won’t hold still.

This site treats the map like a living observation. Its black-fell terrain does not sit behind the writing as decoration: each line is computed from a changing height field, then redrawn while the visitor looks at it.

01 / Concept

One map, ten autumns.

The invented project needed a visual language that respected slowness without becoming sleepy. The large, low headline acts like a horizon. The field ledger is a measured interruption in moss green. The later walk entries use the narrow, repeated rhythm of a field book: date, named observation, weather.

Peat and chalk make the map feel handled rather than screen-clean; survey orange appears only where a line is important enough to have been marked with a pencil. The page moves at a geological rate so the field remains the dominant experience.

02 / Live field

Contours from an actual height field.

The canvas builds a grid of elevation values every frame. Elevation comes from broad simplex noise, smaller detail and a folded ridge. A Gaussian-shaped local term is added around the pointer, which is why moving over the hero raises a temporary hill instead of merely moving an ornament. The transect has one additional, dated wet-swale term: changing its field sheet shifts a real contour rather than swapping an illustration.

1SampleNoise + ridge + cursor elevation
2ClassifyEach cell is compared to seven levels
3DrawCrossing edges become contour segments
function terrainAt(u, v, time, record) {
  const t = time * .36 + options.phase + (record ? record.phase : 0);
  const broad = simplex.noise2D(u * 2.05 + t * .055, v * 2.05 - t * .035);
  const detail = simplex.noise2D(u * 5.4 - t * .03, v * 5.4 + t * .045) * .28;
  const fold = Math.sin((u * 4.3 + v * 1.25) + broad * 1.8) * .16;
  const dx = u - state.pointerX, dy = v - state.pointerY;
  const cursorHill = options.interactive
    ? state.influence * Math.exp(-(dx * dx + dy * dy) / .008) * .86 : 0;
  const wetSwale = record ? record.water * (Math.exp(-(((u - .58) ** 2) / .035 + ((v - .72) ** 2) / .016))
    + .55 * Math.exp(-(((u - .22) ** 2) / .08 + ((v - .49) ** 2) / .03))) : 0;
  return broad * .7 + detail + fold + cursorHill + wetSwale;
}

const contourPairs = [null, [0, 3], [0, 1], [3, 1], [1, 2], [0, 3, 1, 2], [0, 2], [3, 2], [2, 3], [0, 2], [0, 1, 2, 3], [1, 2], [1, 3], [0, 1], [0, 3]];
const mask = (a >= level ? 1 : 0) | (b >= level ? 2 : 0)
  | (c >= level ? 4 : 0) | (d >= level ? 8 : 0);
if (mask === 0 || mask === 15) continue;
const pairs = contourPairs[mask];
for (let pair = 0; pair < pairs.length; pair += 2) {
  drawSegment(pairs[pair], pairs[pair + 1], px, py, cellW, cellH, a, b, c, d, level);
}

This is the exact terrain sampler and marching-squares cell setup used on both fields. The selected sheet is read once per render, then sampled across the grid. The loop is throttled to roughly 20fps, reuses edge points between cells, caps canvas DPR at 2, and stops when a field is not visible or the tab is hidden. A first static render is painted before each canvas fades in, so the terrain never arrives as a blank block.

03 / Palette + type

Tools with a little soil on them.

Space Grotesk gives the page a practical, engineered headline; IBM Plex Mono carries the coordinates, weather notes, dates and small rules. The spaced mono labels borrow the feel of a survey sheet without doing an old-map costume.

Moss #6B7A4F

Peat #3A2E22

Chalk #E9E4D6

Survey orange #D96C2B

Space Grotesk

BLACK FELL

IBM PLEX MONO
NY 681 347 · 458 M

04 / Iterations

  • Pass 1 — correctness. Hardened the terrain start-up path: missing canvas APIs now fail quietly, and a static first frame remains available before any animation.
  • Animation now waits for the hero to be in view, stops for hidden tabs and reduced-motion changes, and has ResizeObserver/IntersectionObserver fallbacks. The device-pixel ratio remains capped at 2.
  • Pointer elevation is driven by actual pointer activity (including touch press) rather than the browser’s :hover state, so the local hill responds consistently. The marching-squares loop also reuses its edge points instead of allocating them for every cell.
  • Moved the compact layout breakpoint to 820px so the 768px view uses the readable stacked/tablet layout; added shrinking safeguards and 44px targets for site, field and footer links. The placeholder email was replaced with a working in-page route link.
  • Strengthened the hero’s dark terrain wash and added quiet peat backings to its text groups for reliable contrast over live contours; marked the decorative direction rule as hidden from assistive technology.
  • Pass 2 — design depth.
    1. Weak moment: repeated left-gutter sections. Opening, method and closing all used the same polite reading rail. The closing is now a full-bleed peat field with an orange survey line running off the page, while a new transect interrupts the narrative at a radically different scale.
    2. Weak moment: an over-safe evidence grid. The three findings read as equal cards. They now work as a tall peat record, an intentionally dropped chalk annotation and a moss evidence block, giving the section a measured vertical collision instead of another row of panels.
    3. Weak moment: generic motion and underused terrain. Entrance fades were removed; the only continuous movement is the slow, meaningful contour calculation. A second live marching-squares canvas is deferred until the transect approaches, then pauses for reduced motion, hidden tabs and out-of-view states.
  • Pass 3 — complexify.
    1. New field moment: the dated transect. The lower contour field now has four field sheets, from 2016 to 2026. Its native range control changes the note and feeds a measured wet-swale value into the same height function, so each revisit redraws a genuinely different ground condition. The reset button has a deliberate first-sheet state rather than pretending there is something to reset.
    2. Loading and finish. Both terrain canvases paint one still frame before a short reveal; font loading is optional so a slow connection keeps a stable fallback instead of reflowing the page. Social metadata now names the survey and its location on both the field and notes pages.
    3. Final restraint. The new control lives in the transect rather than becoming another dashboard. It adds a small act of fieldwork below the fold while preserving the page’s slow, observational pace and the reduced-motion path.