
The slide-to-confirm button
Buttons, Physics, Transitions
NewFree
Exporting an album’s master as a cutting lathe seen from above: the platter spins up, the carriage brings the head over the edge of the black lacquer and the stylus comes down and cuts the groove towards the middle. The cut radius is the progress: where the groove is cut the lacquer lights up in a fan of iridescent light that stays still while the disc turns, where it is still blank it stays black, glossy and flat. At the end the head lifts and parks and the platter brakes; if the destination drive goes away the stylus jumps up and Retry lowers it into the same groove.
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, viewport-fit=cover">
<title>The mastering lathe</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/instrument-sans@5.3.0/wdth.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/caveat@5.3.0/index.css">
<link rel="stylesheet" href="style.css">
</head>
<body>
<main class="stage">
<!-- the export panel of a music app: the master is cut into a lacquer disc on a lathe seen from above. The stylus
comes down at the edge and cuts the groove inwards as the file is written: the cut part catches the light in
a fan of colours, the blank part stays black and glossy. The disc, the head and the light are painted on the
canvas; the words and the button are HTML -->
<section class="lathe" aria-labelledby="lathe-title" data-lathe>
<div class="lathe__deck" role="progressbar" aria-labelledby="lathe-title" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0" data-bar>
<canvas class="lathe__paint" aria-hidden="true" data-paint></canvas>
<div class="lathe__top" aria-hidden="true">
<p class="lathe__phase">
<span class="lathe__swap" data-phase>Ready to export</span>
<svg class="lathe__tick" viewBox="0 0 24 24" data-tick><path d="M5.5 12.6l4.1 4.1L18.6 7.4" pathLength="1"/></svg>
</p>
<p class="lathe__note"><span class="lathe__swap" data-note></span></p>
</div>
<div class="lathe__bottom" aria-hidden="true">
<p class="lathe__big"><span class="lathe__swap" data-big></span></p>
<p class="lathe__time"><span class="lathe__swap" data-time>24-bit WAV · 96 kHz</span></p>
</div>
</div>
<div class="lathe__foot">
<div class="lathe__file">
<h2 class="lathe__title" id="lathe-title">Night Swim (Master).wav</h2>
<p class="lathe__meta" data-meta></p>
</div>
<button class="lathe__btn" type="button" data-action data-autoclic><span class="lathe__label" data-label>Export master</span></button>
</div>
<p class="sr" role="status" aria-live="polite" data-live></p>
</section>
</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.
37 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 mastering lathe” from Animorio and fit it into my siteA groove is nearly a circle, so how it reflects does not depend on how far the disc has turned but only on where it is on the screen: the fan stays still while the disc turns. So the cut lacquer is painted once only, pixel by pixel with getImageData, in screen space, and every frame only clips the cut ring, between the stylus and the edge, with two arcs and clip().
For every pixel the groove’s direction is T = (−sin θ, cos θ) and H is the vector halfway between the light (50° up, top left) and the eye. A fibre’s highlight is (1 − (T·H)²) to a power: with T·H = |H| sin(θ − φ) it lights up only along the line through the light and the centre, on both sides, narrow with the power 520 and wide with 30. On the side of the light it weighs more.
Round the white core the grooves work as a diffraction grating: the colour goes with the angle, from blue near the line to red further out, taken from a table of 65 wavelengths between 410 and 690 nanometres. Each song has a slightly different pitch, so its colours sit a little further in or out. In the smooth rings between songs and in the lead-out the lacquer is a mirror again: a very thin line, few colours and the reflection of the softbox.
The side is split into lead-in, songs, gaps and lead-out, each linear both in progress and in radius: the songs take radius in proportion to their length, the gaps little radius but a little time, so between songs the head runs in faster and leaves the smooth ring. The stylus’s radius, the song’s name and the time on the side all come from the same list.
What turns is a mask in the disc’s own space: louder and quieter passages along the radius and the beat as faint spokes, cos((3 + k)·θ + 0.22·r). Every frame it is drawn rotated into a working canvas, the fan goes into it with source-in and the result is added to the lacquer with lighter. The grease pencil note, laid letter by letter along an arc, and the clamp’s screws turn with it; the light on the clamp’s rings stays still.
The platter has inertia (GSAP takes the speed up and down, the angle adds up every frame); the stylus follows the file writer on a damped spring that never goes back, and wherever it touches the lacquer the cut radius gets shorter. Lifted, the head comes 6% nearer the eye and its shadow moves away and softens. The panel is a role=progressbar with aria-valuenow and aria-valuetext («48 percent, Pale Harbour, 8:01 of 16:27»), aria-busy while it works and an aria-live line; a click from a script, the preview’s, never pauses.
| Name | File | Default | What it changes |
|---|---|---|---|
SECONDS | script.js | 9 | How long an export takes in the demo, in seconds (a real one follows the file writer). |
TRACKS | script.js | [['Undertow', '4:12'], ['Night Swim', '3:48'], ['Pale Harbour', '5:06'], ['Last Ferry', '3:21']] | The songs on side A, from the edge inwards: title and length. The lengths set how much radius each one takes, the side’s length and the file’s size. |
RPM | script.js | 33.33 | The platter’s speed while it cuts, in turns a minute (45 for a single). |
SPINUP | script.js | 1.1 | The seconds the motor takes to bring the platter up to speed. |
BRAKE | script.js | 2.4 | The seconds the platter takes to stop at the end. |
FAIL_EVERY | script.js | 2 | In the demo, one export in how many goes wrong (0 never). |
FAIL_AT | script.js | 0.58 | How far the export that goes wrong gets, from 0 to 1. |
DRIVE | script.js | 'Masters' | The drive that goes away then, and where the master is saved. |
STALLS | script.js | 1 | How often the file writer stops for a moment: 0 never, 1 now and then, 2 often. |
FOLLOW | script.js | 0.3 | How long the stylus takes to catch up with the file writer, in seconds. |
SHEEN | script.js | 1 | How bright the fan of light on the grooves is: 0 none, 1 as cut. |
RAINBOW | script.js | 1 | How much colour the grooves split the light into: 0 none, 1 like a record. |
LIGHT | script.js | 225 | Where the light comes from, in degrees round the disc (0 right, 90 below, 225 top left). |
For a wait of a few seconds or a few minutes in an app that works with sound: exporting a master or a mix, bouncing a session, converting an album, uploading a record to a distribution platform. The groove being cut says «I am writing your music from start to finish» better than a bar, and the songs going by say how far along it is; for a short wait without an outcome it is too much.
The panel takes the screen’s width less 32 pixels (358 on a 390 screen): the disc goes from 200 to 186 pixels, so 118 pixels are left beside it for the words, and the parked carriage still sits inside its rails. The lacquer’s paintings are made again at the screen’s real density, up to twice, only when the disc’s size changes. A long line wraps (above) or ends in an ellipsis (below). The button is a pill 36 tall: under a finger it squashes and springs back, and its words widen on the width axis only under the mouse.
The platter does not turn and the carriage does not run: the head appears already on the edge, goes up and down without bouncing, and from there the stylus follows the progress, because it is what says how far along things are. The fan of light and the colours stay, still as they are anyway. The fresh lacquer arrives as a fade, and new words fade in without moving.
GSAP 3.15.0, Instrument Sans (font variabile) 5.3.0, Caveat (font variabile) 5.3.0.
Compressed with gzip, the three demo files weigh 17 KB; the libraries: GSAP 28 KB.
Tested on 8 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.