SamuelSam Hunt. Builds and paints.

A painting you can smear

The home page has my blue jay painting on it, drawn in letters. Press and drag across it and the paint smears. Let go and it settles back. It's one <pre> tag and a few hundred lines of TypeScript.

The idea came from p.cv, Paul Macgregor's site, which has an ASCII fire you can hold down to light. I wanted the same feeling, but with a painting, because that's what I do when I'm not building.

One number per letter

The painting is drawn onto a canvas the size of the grid: one pixel for every character that fits on screen. Characters are taller than they are wide, so the image is squashed to match before it's sampled, or the bird comes out stretched.

Each cell gets one number between 0 and 1. The obvious choice is darkness, but the jay has a white chest that's almost the same brightness as the canvas, and it vanished. So the number is whichever is bigger: how dark the patch is, or how colourful it is.

const dark = 1 - (0.3 * R + 0.59 * G + 0.11 * B) / 228
const chroma = (Math.max(R, G, B) - Math.min(R, G, B)) / 255
base[i] = clamp((Math.max(dark * 1.3, chroma * 1.2) - 0.16) / 0.84)

The 0.16 knocks out the faint grain of bare canvas, which otherwise fills the background with dots. The number then picks a character from a ramp that goes from a space to an @.

The knife

Dragging doesn't paint. It moves paint. For every cell under the knife, it pulls the value from the cell behind the direction you're moving, and adds a tiny bit more, like a loaded palette knife. Cells near the edge of the knife move less than cells in the middle.

cur[t] = cur[t] * (1 - 0.85 * k) + cur[from] * 0.85 * k + 0.05 * k

Fast drags are split into steps one character apart, so a quick swipe leaves a stroke instead of a dotted line.

Settling back

Two and a half seconds after you stop, every cell drifts 2.5% of the way back to the painting on each frame. It reads as the paint slowly levelling out. When nothing is moving, the loop stops, so the page costs nothing while you read it.

More