
The curtain menu
Menus, Physics, WebGL, Transitions
NewFree
A scene rendering in a 3D app, and the progress is a spiral galaxy taking shape: fourteen thousand stars and seven hundred clouds of coloured dust start as a shapeless cloud and, as the work goes on, spiral down onto their orbits, line up into two arms that wind tighter and tighter, the pink, violet and blue dust draws them and the core lights up. Under it, the phase of the render and the percentage, which widens and gets heavier on the axes of the font. Pause stops the galaxy, a lost render node stalls it and lets it come apart in red until Retry pulls it back with a spring; done, the galaxy winds up, is pulled into one point and comes out of it as the ring and tick of the finished render. All in WebGL, with a canvas fallback.
A folder that runs on its own: index.html, style.css, script.js and the libraries from a CDN.
<!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 galaxy loader</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/saira@5.3.0/wdth.css">
<link rel="stylesheet" href="style.css">
</head>
<body>
<main class="stage">
<!-- the galaxy loader: a 3D app rendering a scene, and the progress is a spiral galaxy taking shape. Thousands of
stars and a few hundred clouds of coloured dust start as a loose, shapeless cloud; as the render goes on they
spiral in and settle onto their orbits, the arms wind up, the dust lines them and the core lights up. Under it
the phase and the percentage. Pause, a lost render node, and at the end the galaxy is pulled into one point
and comes out as the tick of the finished render. The galaxy is painted by script.js, in WebGL, or on a 2D
canvas when WebGL is missing -->
<section class="gx" aria-label="Scene render" data-galaxy>
<div class="gx__sky" role="progressbar" aria-label="Render progress" aria-valuemin="0" aria-valuemax="100"
aria-valuenow="0" aria-valuetext="Ready to render" data-sky>
<canvas class="gx__paint" aria-hidden="true" data-paint></canvas>
</div>
<div class="gx__readout">
<div class="gx__words">
<p class="gx__title">
<svg class="gx__tick" viewBox="0 0 24 24" aria-hidden="true" data-tick><path d="M5.5 12.6l4.2 4.2 8.8-9.4" pathLength="1"/></svg>
<span class="gx__swap" data-title>Ready to render</span>
</p>
<p class="gx__meta"><span class="gx__swap" data-meta>Orangery · 3840 × 2160 · 512 samples</span></p>
</div>
<p class="gx__pct" aria-hidden="true" data-pct>0%</p>
</div>
<div class="gx__buttons">
<button class="pill" type="button" data-go data-autoclic><span class="pill__label" data-label>Render scene</span></button>
<button class="pill is-quiet" type="button" hidden data-again><span class="pill__label">Render again</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.
56 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 galaxy loader” from Animorio and fit it into my siteThe galaxy follows the density wave theory: every star runs on an ellipse with a semi-major axis a and a flatness e(a), and each ellipse is turned a × TWIST from the one inside it. Where neighbouring ellipses crowd together, a quarter turn behind their long axis, the density rises and two spiral arms appear without being drawn. The old stars move along their ellipse at 0.32/(0.16 + a) radians a second (faster inside), the whole pattern of ellipses turns at 0.12: the stars pass through the arms, the arms stay.
An ellipse’s radius at an angle ψ from its long axis is about a(1 − e sin²ψ); differentiating by a shows that the ellipses are closest where sin 2ψ = −1, at ψ = −π/4 and 3π/4. That is where the dust and a third of the stars (the young blue ones) are born, with a spread that grows outwards, and they stay still in the frame of the ellipses: they turn with the pattern, so the arms are always marked in colour. A veil of 170 big, faint clouds of old light fills the disc between one arm and the next.
Every particle is twelve numbers in a fixed buffer: its orbit, a random number, its place in the cloud, its delay in the tick, its place in the tick, its size and its kind. Every frame the vertex shader works out, for each one, the orbit, how far it has settled (a threshold that depends on the radius and on chance: inside first), the spiral it arrives on from the cloud, the coming apart of the error, the collapse into the core, the galaxy’s tilt with a light perspective and its place in the tick. The stars are soft points added up as light; the core is one triangle over the canvas with three gaussians squashed by the tilt.
When the work is done the galaxy’s time speeds up to five times and the arms wind a further 2.2 radians; the collapse brings every star to the middle as it turns it, the inner ones first. In the point there is a flash, and the tick forms in the shader on a hand-written spring, 1 − e^(−5.5t)·cos(8.5t), which overshoots and comes back: first the ring, drawing itself round, then the tick from its short side, because each star has its own delay along the line. The tick’s stars are fainter than the ring’s, which are sparser, so no part burns to white.
The work moves at a speed that wanders a little (three sines laid together) and the galaxy chases it with 1 − e^(−3.2·dt), so it never jumps. GSAP carries the states’ values: pause takes away the rotation and some colour, the error brings err to 1 (the stars move out by a factor that differs for each and take the --lost tint) and Retry brings it back to 0 with elastic.out, which for a moment pulls the galaxy in tighter than it should. The percentage follows font-stretch from 72 to 112% and the weight from 300 to 620.
If WebGL is missing (or lost) a fresh canvas takes the old one’s place and the same formulas run in JavaScript on 3600 stars and 430 clouds, painted as added light. With reduced motion nothing travels: the cloud, the still galaxy and the tick are three layers that fade into each other. The preview’s script click (detail 0) plays the whole round with GSAP, render, lost node, Retry, pause, Resume, tick and back to the cloud; script clicks during the round are ignored. When nothing moves the loop takes itself off the ticker.
| Name | File | Default | What it changes |
|---|---|---|---|
SECONDS | script.js | 6 | How long the demo’s render takes, in seconds, without the pauses and the tick at the end (a real one follows the server’s work). |
STARS | script.js | 14000 | How many stars the galaxy has; on the canvas without WebGL 3600 at most. |
DUST | script.js | 720 | How many clouds of coloured dust mark the arms. |
TWIST | script.js | 5.2 | How far the arms wind: the higher, the more turns the spiral makes and the tighter they are. |
TILT | script.js | 60 | How far the galaxy is tilted, in degrees: at 0 it is seen face on, at 80 almost edge on. |
SPIN | script.js | 1 | How fast it turns while it works. |
FAIL_EVERY | script.js | 2 | One render in how many, started by hand, loses its render node: 0 never. |
FAIL_AT | script.js | 0.46 | How far into the render the node is lost, from 0 to 1. |
TOUR | script.js | [0.5, 0.86] | In the library preview’s round: where the node is lost and where it is paused, from 0 to 1. |
PHASES | script.js | [[0, 'Loading assets'], [0.12, 'Building geometry'], …] | The render’s phases written under the galaxy: where each one starts and what it is called. |
LABELS | script.js | { pause: 'Pause', resume: 'Resume', retry: 'Retry', saving: 'Saving…', done: 'Open render', opened: 'Opened' } | The button’s words in every state; the one at rest, Render scene, is changed in index.html. |
WORDS | script.js | { busy: 'Rendering your scene', paused: 'Render paused', … } | The lines under the galaxy while it works, paused, on the error and at the end; the ones at rest are changed in index.html. |
For a wait of a few seconds or a few minutes in a product that makes something: a scene render, a video export, a generated image or model, a big import, a project build. The galaxy says how far along things are even without reading the number (first the core, then the arms, then the whole disc), and the final tick is a finish line you can see. It suits a creative, scientific or space app, on a dark background; for a very short wait or in a sober admin interface it is too much.
The component is 380 pixels wide and on a phone takes the width of the screen less 16 pixels a side (358 at 390): the sky scales together, the canvas is painted at the screen’s real density (up to twice) and the galaxy, the core and the tick are measured from the canvas, so they stay sharp and centred at any size, even when the window changes height mid-render. The same stars and the same states as on a computer. With a finger held on the sky the galaxy tilts as under the mouse (the sky still lets vertical scrolling through); a touch on Render scene stirs the cloud like the mouse passing over it.
Nothing travels: the galaxy does not turn, the cloud does not stir, the sky does not tilt. The cloud, the still galaxy (arms already in place) and the tick are three layers: as the work goes on every star fades from the cloud into its place in the galaxy, and at the end the galaxy fades into the tick. Error and pause change only colour and light; the words change with a fade and the tick in the text appears without drawing itself.
GSAP 3.15.0, Saira (font variabile) 5.3.0.
Compressed with gzip, the three demo files weigh 18 KB; the libraries: GSAP 28 KB.
Tested on 17 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.