
Stacking certificates
Hover, Images
NewFree
A photo made only of contour lines, in the minimal style: on black, a still life with a vase and a sphere is drawn by hairline lines joining the points of equal brightness, as on a map. On opening the lines draw in from the darkest to the lightest, and a thin glint runs along each one. The pointer is a lens on a spring that spreads and lifts the nearby lines like a swelling relief, and the line under it turns vermilion; a tap fades in the real photo they come from.
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>Isoline</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/hanken-grotesk@5.3.0/index.css">
<link rel="stylesheet" href="style.css">
</head>
<body>
<!-- a still life drawn only with the contour lines of its brightness: the lines draw in from dark to light, the
pointer is a lens that lifts and spreads them like a swelling relief, a tap fades in the photo they come from -->
<main class="pagina" data-pagina>
<header class="testa">
<p class="marchio" data-entra>Isoline</p>
<p class="testa__nota" data-entra>Photography in contour</p>
</header>
<figure class="quadro" data-quadro>
<canvas class="tela" aria-label="A still life of a vase and a sphere drawn with contour lines" data-tela></canvas>
<figcaption class="didascalia" data-entra>Still life with vase and sphere</figcaption>
</figure>
<footer class="piede">
<p class="nota" data-entra data-nota>Move to lift the lines, tap for the photo</p>
<p class="stato" data-entra>Showing <span data-stato>lines</span></p>
</footer>
</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 “The photo drawn in contour lines” from Animorio and fit it into my siteThe photo is not loaded: it is a function that, for every point of the picture, says how bright it is. The wall has a soft light coming from the left, the table starts at 70% of the height with two cast shadows stretched to the right, and the vase and the sphere are shaded like real solids, with diffuse light, a highlight and a bounce from the table below. The edges are blurred by a few thousandths, so the lines don't step.
The light is read on a grid of 168 by 210 points, smoothed twice, and for each of the sixteen levels the script looks for the cells where the light crosses it (marching squares, with the saddle cases resolved by the average at the centre). The pieces of each cell are joined into long lines by following their shared edges, so every line has a start, an end and a length.
Each line draws from one end to the other with a dash as long as itself, and level k starts when the opening reaches k: the darkest first. Once the opening is done a second dash, short and far apart, slides along every line at a steady speed, with a different delay for each level: that is the glint.
Every point near the pointer moves away from the centre of the lens and rises, more if its line is light: with a weight that falls like a bell, exp(-(d/R)²), the lens looks like a relief swelling. The lens chases the pointer on a spring (SPRING) and fades out slowly when the pointer leaves. The line passing under the pointer is drawn again in vermilion, with a gradient that vanishes away from the lens.
The same function draws, once, on a separate canvas of 320 by 400, the photo in warm greys; a tap takes it from 0 to 1 in almost a second with power2.inOut, and the lines are veiled. When nobody moves the pointer, a fake pointer wanders over the picture and now and then shows the photo for two seconds.
| Name | File | Default | What it changes |
|---|---|---|---|
LEVELS | script.js | 16 | How many contour lines: more lines, a finer drawing. |
LENS | script.js | 1 | How strongly the pointer lifts and spreads the lines: 0 switches the lens off. |
RADIUS | script.js | 0.24 | How wide the lens is, as a share of the picture's width. |
SPRING | script.js | 7 | How quickly the lens follows the pointer: less is softer and later. |
GLINT | script.js | 1 | How bright the glint running along the lines is: 0 switches it off. |
DRAW | script.js | 2.6 | How many seconds the lines take to draw in. |
LINE | script.js | 1 | How thick the lines are. |
On the page of a photographer or a photo studio, as the opening image of a gallery or a portfolio; for a mapping agency, a science museum or an exhibition about light; anywhere a photo should arrive slowly, first as a drawing and then as an image.
The same animation: the picture is sized on both width and height, so it fits the box. A dragging finger is the lens, a tap shows the photo; the line at the bottom says drag instead of move.
The lines are all drawn already and still: no glint, no lens, no fake pointer. A tap goes to the photo and back with a fade only, and the labels fade in.
GSAP 3.15.0, Hanken Grotesk (font variabile) 5.3.0.
Compressed with gzip, the three demo files weigh 6.9 KB; the libraries: GSAP 28 KB.
Tested on 24 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.