Flow Field

Hundreds of particles ride a seeded, slowly changing vector field and leave fine fading trails, as a seamless loop

Installation
$ pnpm dlx shadcn@latest add @remocn/flow-field

Usage

FlowField draws particles that follow a vector field across the frame. The field angle at each point is a sum of four seeded sine waves, and it shifts slowly over the loop. Each particle is born at a seeded position, sometimes just outside the frame, and steps along the field for its life. Its head moves first and the trail grows behind it; then the head stops and the tail catches up, so trails grow in and drain out instead of popping. Births are spread over the life, so the frame always holds a steady population.

Each trail is split into six age segments that get fainter and thinner toward the tail. A seeded share of particles, accentRatio, is drawn in accent.

tsx
import { FlowField } from "@/components/remocn/flow-field";
 
export const Texture = () => <FlowField />;

The component fills its parent and paints its own background. Particle speed and stroke width scale with the short side of the composition, and strokeWidth is in px at 720p. Positions come from Remotion's seeded random(), so a seed always produces the same field and every frame renders the same way.

Timing

The field and every particle's life cycle repeat every loopFrames / speed frames, 300 frames (10 seconds) at the defaults. The last frame of the loop flows into the first without a seam, so a Sequence of any multiple of the period, or a Remotion <Loop> of that length, plays as a continuous background.

A particle lives loopFrames / round(loopFrames / lifeFrames) frames, 150 at the defaults, so a whole number of lives fits in one loop. The trail is capped at 60% of the life: the head travels for life − trail frames, then holds while the tail drains.

There is no build-up: frame 0 already shows a full population.

Performance

Each frame recomputes every visible trail from the particle's birth, so the cost grows with particles × lifeFrames. The defaults render quickly; 800 particles with 300-frame lives is about five times heavier. Lower particles before lowering trailLength if renders get slow.

Variations

A high trailLength with a low particles count gives long, sparse strands. accentRatio={0} keeps the field monochrome, and accentRatio={1} draws everything in the accent. Change seed for a different field layout.

tsx
<FlowField
  particles={160}
  trailLength={110}
  strokeWidth={2}
  accentRatio={0.25}
  background="#0b1020"
  color="#9fb4ff"
  accent="#ffffff"
  seed={5}
/>

Props11

PropTypeDefault
particles
number300

Particles in flight

trailLength
number72

Trail length in frames of travel, capped at 60% of the particle life

loopFrames
number300

Frames for one seamless loop of the field and the particle life cycles

lifeFrames
number150

Particle lifetime in frames, adjusted so a whole number of lives fits in loopFrames

accentRatio
number0.1

Share of particles drawn in the accent color, 0 to 1

strokeWidth
number1.4

Trail width in px at 720p, at the head; older segments thin to half

seed
number1

Seeds the field, the spawn points and which particles take the accent

background
string"#111111"

Background fill

color
string"#FFFFFF"

Trail color

accent
string"#E5322D"

Color of the accent share of trails

speed
number1

Playback multiplier; the loop period is loopFrames / speed

  • particlesnumber

    Particles in flight

    Default300

  • trailLengthnumber

    Trail length in frames of travel, capped at 60% of the particle life

    Default72

  • loopFramesnumber

    Frames for one seamless loop of the field and the particle life cycles

    Default300

  • lifeFramesnumber

    Particle lifetime in frames, adjusted so a whole number of lives fits in loopFrames

    Default150

  • accentRationumber

    Share of particles drawn in the accent color, 0 to 1

    Default0.1

  • strokeWidthnumber

    Trail width in px at 720p, at the head; older segments thin to half

    Default1.4

  • seednumber

    Seeds the field, the spawn points and which particles take the accent

    Default1

  • backgroundstring

    Background fill

    Default"#111111"

  • colorstring

    Trail color

    Default"#FFFFFF"

  • accentstring

    Color of the accent share of trails

    Default"#E5322D"

  • speednumber

    Playback multiplier; the loop period is loopFrames / speed

    Default1