← All effects

Halftone Waves

BackgroundVanilla JS · zero dependenciesdot size = the wave, sampled on a grid
-- fps
prefers-reduced-motion detected — the wave is shown frozen

X-ray · layers

render as halftone dots (off = the raw grayscale wave)
the field travels (off = frozen)
a second wave rings out from the center

Parameters

Cell size24 px
Wave speed1.0×
Dot scale0.90
Hue262°
your version · updates as you tinker

How this effect works

Under the hood there's an invisible wave field — a number for every point that rises and falls with sin(x, y, time). On its own you'd draw it as a smooth gradient (flip the dots layer off to see exactly that). The halftone trick is to sample that field on a grid and, at each grid point, draw a dot whose radius is the field's value there. Where the wave is high the dots are fat; where it's low they shrink to nothing — the same way a printed newspaper fakes shades of gray with nothing but black dots of different sizes.

The cell size is the grid spacing (smaller = finer, more dots), dot scale caps how big a dot can get relative to its cell, and speed scales time. The ripple layer adds a second wave that rings out from the center, and where it meets the first they add up — so the dots pulse in interference patterns nobody drew by hand.

Production notes: respects prefers-reduced-motion (frozen frame) · cost = grid cells × 1 circle; the cell-size slider is the real performance dial · the smaller the cell the more dots, so it is floor-capped · the copied snippet is self-contained HTML + JS.