Study 02 / Ink Current

The current is designed by its eraser

Ink Current stores no stroke. A bounded tracer population draws one segment per frame; velocity damping and a time-corrected framebuffer wash decide how long the gesture remains visible.

Which should disappear first: the motion or its visible trace?

Open the live system
Ink Current dual-memory proofA sequence of fading curved traces crosses five ruled frames. A playback line separates the shorter optical memory from the longer particle-velocity memory.
Image memory
~130ms half-life
State memory
~408ms half-life
The gesture is not stored. Short segments accumulate, fade, and leave particle velocity to outlive its brightest trace.
Published
Jul 12, 2026
Updated
Jul 12, 2026
Reading
10 min
On this page
  1. The vanishing mark
  2. Bounded population
  3. Direction from phase
  4. Pointer injection
  5. Two decay clocks
  6. Boundaries and stillness
  7. Where residue belongs

01 / Ink Current / The vanishing mark

The line is never stored.

Ink Current does not record a stroke. There is no path buffer and no stream of particles emitted beneath the pointer. The scene begins with an existing population, remembers each particle’s previous position for one frame, and draws only the short segment from that position to the next.

The longer mark is assembled by the framebuffer. New segments are added with lighter compositing while a dark wash removes part of the previous image. What looks like a continuous line is accumulated light: a sequence of temporary observations, not stored geometry.

That distinction defines the pattern’s limits. It can make movement legible, but it cannot reproduce a signature, edit a drawn path, or tell the visitor exactly where a gesture travelled.

The mark is reconstructed every frame
  1. 01Sample

    One time-normalized pointer displacement

  2. 02Couple

    A 210px field with linear falloff

  3. 03Advance

    One previous-to-current segment

  4. 04Erase

    A delta-corrected framebuffer wash

The trail is the time it takes a frame to forget.

02 / Bounded population

Density is authored before motion begins.

The tracer count follows the Canvas area. Small viewports keep a floor of 240 particles; large ones stop at 520. The ceiling bounds per-frame work, while the floor prevents the current from becoming visually empty on mobile. Every non-wrapping particle contributes at most one line segment per frame, so update and drawing work remain linear with the population.

Viewport area sets a bounded tracer budget
round(clamp(width × height ÷ 3100, 240, 520))

The default seed 1108 assigns initial positions, phase offsets, and sizes from 0.7px to 2px. Cyan, violet, and pink cycle by array index. This makes the initial distribution repeatable for a given viewport, but it does not encode data or particle identity. The population is art-directed texture, not a visualization.

Resize rebuilds that population. The scene is deterministic at initialization, not immutable over time: viewport dimensions, scene-local phase, and pointer input still determine the live result. The catalog count used by Sparks has no effect here.

03 / Direction from phase

Direction comes from phase, not fluid.

Each tracer receives an angle from two slow trigonometric waves. The x term spans roughly 1,047 CSS pixels per cycle and changes over about 28.6 seconds; the y term spans roughly 785 pixels and changes over about 37 seconds. A per-particle seed shifts the first phase, so two tracers at the same coordinate do not necessarily receive the same direction.

The direction rule evaluated for each tracer
theta = 1.55 sin(0.006x + 0.00022t + seed)
      + 1.15 cos(0.008y - 0.00017t)

velocity += 24 * delta * (cos(theta), sin(theta))
position += 60 * delta * (velocity + 0.44 * direction)

The implementation converts the angle into a unit direction with cosine and sine, adds directional acceleration, and advances position against a 60Hz reference. This keeps the composition’s approximate pace stable across common refresh rates without pretending the constants are physical units.

It is an analytic steering rule, not a fluid simulation. There is no pressure, density, incompressibility constraint, neighbor exchange, noise texture, or grid solver. The model borrows the visual language of a current because curved routes are useful here; it does not claim to predict one.

04 / Pointer injection

The pointer contributes a pulse, not a stroke.

Movement is converted into a 60Hz-reference displacement sample. Each axis is normalized by the time between pointer events, then capped at ±28px. The first move after the pointer enters the active field contributes no travel velocity. Later samples receive a linear envelope that falls from one to zero over 120ms, so the final event cannot drive the scene forever.

Event displacement normalized to one reference frame
u = clamp(
  displacement * ((1000 / 60) / elapsedMs),
  -28,
  28
)

Only tracers within 210px respond. A linear falloff reaches zero at that boundary. Hover applies a direct gain of 0.34; pressing raises it to 0.90. A second, tangential term uses the perpendicular vector (−dy, dx) to bend local motion, with gains of 0.6 for hover and 1.5 while pressed. Press changes strength, not the direction of the model. At the baseline intensity those gains are unscaled; the controller bounds their shared multiplier between 0.4 and 1.6.

Pointer injection cross-sectionA horizontal 210 pixel influence field falls linearly to zero. A direct arrow follows pointer travel while a perpendicular arrow bends nearby motion.−210 PX0+210 PX
Radius
210px
Direct gain
0.34 / 0.90
Tangent gain
0.60 / 1.50
Direct travel and a perpendicular bend share the same bounded, linearly fading footprint.

Links, controls, and the reading surface are excluded from this field. Pointer feedback belongs to open space; selecting text or activating navigation should not inject motion into the artwork. Touch has no hover phase, and vertical movement remains available to page scrolling through touch-action: pan-y.

05 / Two decay clocks

State and image forget at different rates.

Particle velocity is multiplied by e^(−1.7 × delta). In the absence of the continuing direction rule and pointer force, that gives added velocity a half-life of about 408ms. The overall field never settles because procedural steering continues; the number describes gesture memory above that ambient movement.

The visible trace uses a shorter clock. At the 60Hz reference, each frame applies a dark wash with alpha 0.085. For an arbitrary frame delta, the equivalent clear alpha is derived from the same retention value. This preserves an optical half-life of about 130ms instead of letting a 120Hz screen erase the image twice as fast as a 60Hz screen. The displayed 0.085 value is intensity 50; the bounded controller moves reference wash alpha from 0.14 toward 0.03 as energy rises, so higher energy also leaves a longer trace.

Two clocks decide what remains
Optical trace~130ms

Framebuffer retention derived from 0.915 at the 60Hz reference.

Particle velocity~408ms

Exponential damping in the absence of continuing field or pointer force.

The reviewed framebuffer wash
alpha(delta) = 1 - (1 - 0.085)^(60 * min(delta, 0.032))

The Ink integrator caps its local delta at 32ms, inside the shared loop’s 34ms cap. Position and direct input use the same reference frame scale as the framebuffer wash. Discarding excess elapsed time prevents one oversized step after a stall, although the visible scene will briefly run behind wall-clock time.

06 / Boundaries and stillness

Edges wrap; reduced motion changes the drawing.

Tracers travel slightly beyond the visible field before wrapping at −12px andwidth + 12px, or the corresponding vertical bounds. A wrap does not draw a segment. The previous position is reset to the destination and that frame is skipped, preventing a false line from cutting across the entire Canvas.

Work remains bounded but not free. Each active frame evaluates trigonometric functions, updates and strokes 240–520 tracers, and washes the full backing store. The loop is O(n), unlike Sparks’ pair scan, while a DPR ceiling of 2 prevents backing-store area from growing without limit. A material resize rebuilds transient scene runtimes from their current seeds, but the Garden field remains lazy and controller settings are retained.

The animated system stops when the document is hidden or the landing leaves the viewport. With prefers-reduced-motion: reduce, requestAnimationFrame never starts. Ink renders a separate still composition instead: 34 sine paths distributed through the central field, sampled every 12px, with amplitudes from 28px to 64px and alternating cyan and violet strokes. Its phase reflects the current seed without changing live tracers.

Reduced-motion current specimenA representative subset of layered sine paths forms a calm static current without continuous animation.
The live fallback draws 34 authored sine paths; this specimen shows the same still-image grammar at article scale.

That still is not a frozen simulation frame. It is an authored substitute that communicates layered direction without continuous tracking. The Canvas remainsaria-hidden; explanation, instructions, and destinations live in ordinary HTML. The visible Pause / Resume transport now sits outside that hidden subtree. User pause preserves the current framebuffer and tracer state, while the reduced-motion preference continues to select this separate still composition.

07 / Where residue belongs

Use residue only when residue has a job.

Ink Current suits an ambient editorial field, a short transition, or nonessential feedback where seeing movement persist briefly clarifies that an input had direction and consequence. It works best behind stable content, inside a bounded region, and with a conventional interface carrying every important action and label.

  1. 01
    Useful feedback

    A short trace confirms direction, then clears before the next task begins.

  2. 02
    Lingering decoration

    The mark remains after its meaning has passed and starts competing with copy.

  3. 03
    Noise

    Residue is mistaken for durable state, exact geometry, or a selectable route.

It is the wrong model for signatures, handwriting, route capture, or any tool that must reproduce a gesture: no path is stored. It should also stay away from dense forms, precise comparison tasks, and status communication, where luminous residue can obscure information or be mistaken for state.

The test is simple. If a fading trace helps explain that input had direction and consequence, the effect has a reason to exist. If the visitor must inspect the trace to understand what happened, use explicit geometry, durable state, and semantic feedback instead.

Method

References and implementation sources

This article documents the live implementation running on this site. These primary standards and publication records were used to verify API behavior and technical terminology.

  • HTML Canvas 2D ContextWHATWG HTML Living Standard

    Path drawing, alpha compositing, and state used by the tracer and framebuffer wash.

  • Pointer Events Level 3W3C

    Unified pointer input and capture semantics used for injection and cancellation.