PRO

Wind Drift Field

Still air you stir with the pointer, running on a real fluid solver rather than a painted force field. Fourteen thousand tracers ride the velocity field and leave trails that fade back into the paper, and every trail is coloured by the speed of the air carrying it, so a slow eddy stays green and a hard sweep burns red. The air is a Stable Fluids grid and the three steps in its loop are what make it read as wind rather than as blobs. Self-advection carries the velocity field along itself, so momentum keeps travelling after your hand stops and a stroke moves downstream and stretches instead of sitting where you drew it. Pressure projection solves a Poisson equation each frame and subtracts the gradient to remove divergence, which is the step that makes air behave like air: without it velocity is created and destroyed in place, which is exactly what a stamped gust looks like, and with it the air pushed out of one place has to go somewhere, so a stroke rolls up into vortices at its ends and the flow curves around itself. Vorticity confinement puts back the small swirls the solver own interpolation smears away, and its gain is capped at half the energy viscosity removes, so a wake stays turbulent without the field ever churning forever. Nothing moves on its own: with the air at rest a tracer draws a zero-length segment and the buffer keeps fading, so the surface sits empty until it is touched, and once the kinetic energy decays the loop parks itself on a cleanly cleared buffer rather than on the residue an eight bit fade can never round away. The trail is a ping-pong pair of framebuffers, so it is never stored as history, only as what is left of the last frame. One WebGL canvas, no library and no asset required.

Component

Still air

Move the pointer to raise a wind

Nothing moves on its own. Colour reads wind speed, green in a slow eddy, red where you sweep hard.

Install
npx shadcn@latest add https://ui.aryank.space/r/wind-drift-field.json

Installs from ui.aryank.space. To add it by hand, copy the files in Usage below, or register the @compronents namespace via the docs.

Files

API
PropTypeDefaultDescription
palettestring[]eight-stop green to redTrail colours from stillest air to fastest, as hex. Sampled continuously, so any length works and intermediate speeds blend between neighbours.
backgroundstring"#0a121b"Field colour. Trails fade toward it every frame, so it is the fade target as much as the backdrop.
particleCountnumber14000Tracers on the field. Each contributes one line segment per frame, and the whole loop runs on a 30fps gate.
turbulencenumber0.6Vorticity confinement, 0 to 1, expressed as a fraction of the energy viscosity is removing rather than as a raw epsilon. It cannot exceed the damping, so no setting makes the air churn forever. Zero lets the solver smooth a wake into a smear.
viscositynumber0.96Velocity kept per frame. Lower brings the air to rest sooner and, because turbulence is scaled against it, also shortens how long a wake stays lively.
gustStrengthnumber1Multiplier on the pointer's push. Zero leaves the air permanently still, which is the right setting behind dense content.
flowSpeednumber2.9How far a tracer travels per unit of air speed. Raising it lengthens every streak without changing the shape of the flow.
drift[number, number][0, 0]Even background breeze in field units per second, added at sample time since a uniform flow is already divergence-free. Zero, the default, is what lets the field sit empty and the loop idle; any non-zero value means it never parks.
showGridbooleanfalseA faint survey grid over the field. Off by default so the airflow reads on its own.
childrenReactNodenoneContent rendered above the field, full height.
Customize
turbulencetext

Small-swirl recovery, 0 to 1, as a fraction of what viscosity removes. Default 0.6.

viscositytext

Velocity kept per frame. Lower settles sooner. Default 0.96.

gustStrengthtext

How hard a sweep pushes the air. Default 1.

backgroundcolor

Field colour. Trails fade into this, so it is the fade target as much as the backdrop.

Dependencies
None.