Pointer · effect

PointerRippleGrid

A field of matte forms on paper, rippling around the cursor.

move the cursor across the field

Paste into Claude Code, Cursor or any agent. Pinned to a tag, so it will not change under you.

Options

paper #fbfaf4

css colour

The paper the field stands on. Match it to your page background or the panel reads as a pasted-in rectangle.

stone #f2efe6

css colour

The forms at rest. Slightly lighter than the paper is what makes them read as objects standing on it.

accent #c44400

css colour

The forms at the crest of the ripple. The colour is what makes the wave legible in a still frame, so do not set it to the same value as stone.

count 18

6 to 40, good: 16 to 26

Forms per side. 18 is 324 of them. Past 30 the forms are narrower than their own shadows and the field turns to fur.

form cylinder

cylinder · box

Shape of each form. Cylinders read as softer and hide the grid; boxes keep the rows visible, which suits a lower count.

thickness 0.58

0.1 to 0.95, good: 0.4 to 0.7

Width of each form as a fraction of its cell. Above 0.9 neighbours touch and the field becomes a surface.

base 0.14

0.01 to 1, good: 0.05 to 0.3

Height of a form at rest. Low is a floor that rises; high is a forest that sways.

amplitude 1.9

0.1 to 4, good: 1.2 to 2.6

How far the crest rises above the base.

frequency 1.9

0.5 to 8, good: 1.5 to 3.5

Rings per unit of distance. Above about 5 the rings are finer than the grid and it aliases into noise.

falloff 0.26

0.05 to 2, good: 0.18 to 0.6

How quickly the ripple fades away from the cursor. Low spreads across the whole field; high is a tight pool underneath it.

elevation 36

8 to 80 deg, good: 25 to 50

Sun height above the horizon. Low throws long shadows between the forms, which is most of what gives the field depth.

shadow 0.26

0 to 1, good: 0.15 to 0.4

How dark the shadows fall on the paper. The paper is never lit, so this is the only thing drawn on it.

softness 0.5

0 to 1, good: 0.3 to 0.7

Shadow edge softness. Zero is a hard midday edge, one is heavy overcast.

tilt 0.6

0 to 1, good: 0.4 to 0.75

Camera height. Zero is eye level with the paper, one looks straight down. Low is dramatic and hides the ripple; high shows the pattern and flattens the forms.

zoom 0.8

0.3 to 1.6, good: 0.6 to 1

How much of the frame the field fills.

period 5

2 to 60 s, good: 5 to 20

Seconds for one loop of the idle swell, the motion used when no pointer is present. Exactly periodic, so the loop closes.

reducedMotionTime 1.4

0 to 60 s

The single frame shown when the user prefers reduced motion. Pick a time where the idle swell has some variation across the field rather than one where it is flat.

What it needs

Dependencies
three@>=0.160.0
Browser
WEBGL1
Frame budget
~7 ms · 1 context
Pinned to
v0.6.2
  • three.js must already be a dependency of the project. It is not bundled
  • One InstancedMesh, so 324 forms cost one draw call and one shadow pass
  • The ripple is a standing wave centred on the cursor, not a propagating one with memory. renderAtTime has to be pure in t, and a wave with history is not
  • 324 instance matrices composed per frame in JavaScript, then one upload
  • The shadow map is the cost, not the geometry. Drop count to 16 before touching anything else

Concept credit: the wave-propagation grid, by Codrops. The implementation here is written from scratch.