One renderer for the gap between "we asked for an image" and "the image arrived",
on any slide. It takes three things it can already know at render time, the slide background, the
accent colour, and the shape the image will occupy, and screens that shape in dots until the
picture lands.
The three slides below share a single function. Nothing about them is special-cased:
a full-bleed rectangle on white, a chevron on dark navy, and a folded polygon on cream all come
from the same call with different arguments.
Wave
Edges
Colour from
Base
Render
Tone
Loop
Three slides, one call
โ
The contract
Why it is built this way
The region is tinted, not outlined. A stroke and an inner glow drew the
container's edge; a low-opacity blue field with a few very large gradients drifting through it
says the same thing without a line. The mask is felt at the tint boundary rather than traced,
which suits an angular shape better, and the slow drift reads as "working" without a spinner.
Stroke and glow are still there at 0 if you want to compare.
Box and shape are separate, because that is how the product models it.
In app.presentations.ai the picture is a .ci-element-image placed in the slide,
carrying a clip-path written in percentages of its own box. The renderer takes the
same two values, so a mask can be lifted from a layout and dropped in here unchanged.
The shape is the source of truth, used twice. The same percentages become
both the clip-path on the arriving picture and a Path2D for the dot
test, so the loader and the image can never disagree about where the image goes.
These are the live values, not a trace. Every box, clip-path, background
and picture below was read out of the three decks in app.presentations.ai, so the geometry is
exact rather than eyeballed. Deck ids are printed on each slide. The Daniels chevrons are the
real thing too: the mood paints a solid accent masked by its own PNGs
(line-tr1.png, line-br1.png), which is why its gold is
#FFBA08 and not the softer tone a screenshot suggests. The Instagram blocks and
the Lenskart purple folds are rebuilt by eye โ that deck's mood has since been changed in the
app, so its original decor is no longer there to read.
Dots are placed by centre, not clipped. Every cell centre is tested against
the shape and skipped if it falls outside. Clipping the canvas instead would slice dots in half
along the edge, which reads as a mistake on an angular mask.
Ink colour is derived, then checked. The accent is used as the dot colour,
but only if it clears a contrast ratio against the slide background. A navy accent on a navy
slide falls back to a tint of the background, so the loader can never come out invisible.
Canvas, not DOM. A full-bleed region at pitch 8 is around 7,000 cells. As
elements that is a stutter; as one canvas with dots batched into eight alpha buckets it is a
few fills per frame.
White noise stops working at this size. Over a few hundred cells a random
per-cell phase reads as lively. Over seven thousand it averages out and the whole region looks
uniform, because at any instant every phase is equally represented everywhere. The fix is
spatial coherence: neighbouring cells need to share a phase so the eye can see a patch. That is
what Clumped, Drift, Rings and Bands are โ a smooth field
instead of noise, with Patch size setting how big a patch is and Coherence
blending back toward pure noise. Random (white) is kept so the difference is visible.
Three phases, because the first one cannot know the picture. At t=0 the
image does not exist yet, so a screen that already outlines the subject is lying. Phase 1 is a
neutral field. Phase 2 begins when a preview lands: preview(toneFn) morphs every
dot from the field toward the picture's own tone, so the noise reorganises itself into a
low-resolution render. Phase 3 swells the dots out as the full picture fades in. Only the
middle phase knows anything, and it only knows what a preview could actually tell it.
Tone is pluggable, and here it is plugged in. Switch Tone to
Neutral field and the screen is decorative, which is all you can do when the picture
is genuinely unknown. Leave it on From image and imageTone() samples the
real photograph, so the dots are a low-resolution render of the picture they resolve into. In
production that sampler would read a tiny preview from the generator rather than the full
image.
The sampler matches the crop, and follows the ink. It applies the same
cover crop the CSS will, so the preview cannot be framed differently from the
photo. And tone means darkness on a light slide but brightness on a dark one, because the ink
flips. Without that, the halftone renders as a negative.