The story of stabilizing a football across 82 photos.
It started with the World Cup 2026. I watched 4 matches live in Boston and it was an epic experience, one of its kind. The energy, the crowd, the moments frozen in photographs.
After the games, I was scrolling through incredible match photos on X and noticed something: the ball is always in a different spot, a different size, sometimes barely visible. What if you could lock it in place and let the world move around it?
I've been writing about Arsenal all season on this site. match recaps, tactical breakdowns, the highs and lows of being a Gooner. Football has been a thread through everything I build. The Gooner Tracker tracks every fixture. The Arsenal blog posts cover every matchday. This project was the visual one. taking the sport and making art from it.
I sourced 82 raw football images from X (Twitter). World Cup 2026 match moments, training sessions, celebrations. The criteria was simple: the ball had to be clearly visible somewhere in the frame.
The first thing I built was an annotation tool. a standalone HTML page where you load each image, click the center of the ball, and drag outward to set its radius. It stores (x, y, radius) in pixel coordinates for every image.
I annotated 64 of the 82 images by hand. The rest were duplicates or had balls too small to meaningfully stabilize (under 6px radius). Each annotation took about 5 seconds. click, drag, next. Arrow keys to navigate. Progress dots at the bottom. Simple, fast, purpose-built.
The core idea is elegant: every image gets scaled so the annotated ball radius becomes exactly 15px on screen, then repositioned so the ball center lands at the exact center of the viewport.
scale = displayRadius / annotation.radius
imageWidth = naturalWidth × scale
offsetX = viewportCenter - (annotation.x × scale)
offsetY = viewportCenter - (annotation.y × scale)
The result: the ball is frozen in place. Players, stadiums, crowds. everything else moves and scales around it. It creates this hypnotic effect when you flip through images quickly.
The viewer evolved over many iterations. It started as a basic image display and grew into a full synth-board interface: play/pause, speed control, timeline scrubber, layer slider (show 0-5 previous images as ghost trails), frame mask with rounded corners, sort options (by number, smallest ball, largest ball, random), and finally GIF export.
The GIF export captures exactly what you see. layers, rounded corners, frame size. using gif.js with a local worker. The 4 GIFs on the main page were all exported from this tool with different sort orders and layer settings.
The full annotation + viewer tool is hosted at /football-wc-26/edit/football-wc-26/edit (open on a computer). Load it up, annotate your own images, and export your own stabilized sequences. Best experienced on a desktop with a keyboard.
Images sourced from these accounts on X:
All images belong to their original creators. Used here for non-commercial creative exploration.