
The swelling lens
WebGL, Hover, Images
NewFree
Three pictures in WebGL: where the pointer passes the photo opens in a hole with a trembling edge, underneath there is white squared paper, and around it the photo ripples like water.
A folder that runs on its own: index.html, style.css, script.js and the libraries from a CDN. The React and Vue tabs hold the same demo as a ready component, which switches its animations off when it leaves the page.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>The squared sheet</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/mona-sans@5.3.0/standard.css">
<link rel="stylesheet" href="style.css">
</head>
<body>
<main class="pagina">
<!-- tre quadri: ognuno ha la sua immagine, disegnata dallo script, e un piccolo WebGL che la mostra -->
<div class="galleria">
<div class="testa">
<p class="nota" data-nota>Move the mouse over the pictures: wherever you pass, the photo opens, and underneath there’s graph paper.</p>
<h1 class="titolo">Under every photo there’s graph paper.</h1>
</div>
<figure class="quadro quadro--campo" data-quadro="campo">
<div class="quadro__tela" data-tela></div>
<figcaption class="quadro__dida">The field, at the end of June</figcaption>
</figure>
<figure class="quadro quadro--finestra" data-quadro="finestra">
<div class="quadro__tela" data-tela></div>
<figcaption class="quadro__dida">The kitchen window</figcaption>
</figure>
<figure class="quadro quadro--brocca" data-quadro="brocca">
<div class="quadro__tela" data-tela></div>
<figcaption class="quadro__dida">The jug and two pears</figcaption>
</figure>
</div>
</main>
<script src="https://cdn.jsdelivr.net/npm/gsap@3.15.0/dist/gsap.min.js"></script>
<script src="script.js"></script>
</body>
</html>Change values, colours and text with the controls and watch the animation respond live. Or write in the code yourself. Then download the folder with your changes.
18 values to change
With the Animorio connector, Claude Code takes it from here, guide included, and fits it into your project. Paste this request:
Take “Squared paper under the photo” from Animorio and fit it into my siteThe shader receives sixteen points: the first is the pointer, the others the trail, each with its position, the time it was born and its radius. In every pixel it adds r² over d² for all of them and cuts the sum at 1: where two holes come close they merge like drops. Trail holes swell in a quarter of a second and close with the square of the time left.
Before measuring, the pixel’s point is warped with two turns of noise that flow over time, at different scales: so the hole’s edge is never a circle and its shape never repeats. The cut is narrow, between 0.96 and 1.04, so it reads as a cut and not as a fade.
The sheet counts how many 24-pixel squares fit in the frame, rounds, and divides the size by that number, for rows and for columns: the squares come out a hair off square, but none is cut. The two far edges are drawn too, and a thread of shadow just inside the cut puts the sheet under the photo.
Each trail hole sends out a wave: a sine inside a bell that runs outward at 260 pixels per second and dies away over time. The wave moves the point where the photo is read along the radius, that is outward from the touch. The sheet does not bend: the water is on the photo.
| Name | File | Default | What it changes |
|---|---|---|---|
CELLA | script.js | 24 | The side of a square in px; the sheet adjusts it to keep only whole squares. |
TESTA, GOCCIA | script.js | 70, 84 | The radius of the hole under the pointer and of the trail holes. |
VITA | script.js | 1.6 | How many seconds a trail hole takes to close. |
TREMA, ONDA | script.js | 34, 16 | How many px the edge trembles and how many the water moves the photo. |
DISEGNI | script.js | campo, finestra, brocca | The three pictures, drawn on the canvas; any photo can be loaded in their place. |
For the photos of a portfolio, a menu or a gallery that must stay photos until someone plays with them: the sheet underneath says there is a plan behind every picture.
The photos stack. A tap opens a hole that closes by itself; dragging sideways draws, vertically the page scrolls as usual.
No trail, no water and no trembling edge: under the pointer there is only the hole, which appears and disappears with a short fade.
GSAP 3.15.0, Mona Sans (font variabile) 5.3.0.
Compressed with gzip, the three demo files weigh 8.9 KB; the libraries: GSAP 28 KB.
Tested on 21 October 2026
Use it in your own projects and in your clients’ projects. Do not resell it or redistribute it as is. GSAP stays under its own Standard license. Full license.
With your account’s email and password.
or with your email
You’re signed in as .
With your account, you can download the zip of every animation and every pack, for free.