Skip to content
animorio
IT
All components

The galaxy loader

Loading, WebGL, Physics, TransitionsWebGL, Canvas, GSAPAdvancedCompressed weight: Demo 18 KBGSAP 28 KBFreeDownload the zip

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.

The code

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>

Playground

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

Or ask Claude Code for it

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 site

What it does

On a black background, alone in the middle, a sky with no edges holding a cloud of grey-blue stars and little pink, violet and blue clouds, scattered in clumps like a nebula, standing still. Below, on the left, the line Ready to render with the scene’s details (Orangery · 3840 × 2160 · 512 samples), on the right a thin, narrow 0%, and in the middle the Render scene button. Pointing at it turns the cloud a little; the sky tilts towards the pointer (with a finger, while it is pressed) and springs back. Pressed, the render starts: the stars near the middle spiral down onto their orbits first, then the ones further out; the orbits line up into two arms that wind tighter as the work goes on, the dust follows them, the young blue stars run inside them and the core lights up with a warm light. The galaxy is tilted, as if seen at an angle, and turns: the stars near the middle faster than those outside, the arms slower than the stars. Below, the line says Rendering your scene and the phase (Loading assets, Building geometry, Tracing light, Denoising, Compositing), and the percentage grows wider and heavier on the axes of the font. Pause slows it down until it stands still and dims it a little: Render paused; Resume sets it going again. If the render node is lost the galaxy stalls, the arms come apart outwards, the stars turn red and the core goes down: Render node lost, Progress kept · retry to go on. Retry pulls it back with a spring and the work goes on from where it was. At a hundred the galaxy speeds up, winds up further, is pulled into its core down to a point that flashes, and from the point the stars fly into a ring that draws itself round and then into a tick, from violet to peach, with a little bounce: Scene rendered with a green tick that draws itself, Saved to Renders · 3840 × 2160, and the Open render and Render again buttons, the second of which sends the stars back to the cloud and starts again.

How it works

Arms that make themselves

The 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.

Dust and young stars on the arms

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.

All in the vertex shader

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.

From the point to the tick

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.

Work, pause, error

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.

Fallback, reduced motion and the demo

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.

Values to change

NameFileDefaultWhat it changes
SECONDSscript.js6How 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).
STARSscript.js14000How many stars the galaxy has; on the canvas without WebGL 3600 at most.
DUSTscript.js720How many clouds of coloured dust mark the arms.
TWISTscript.js5.2How far the arms wind: the higher, the more turns the spiral makes and the tighter they are.
TILTscript.js60How far the galaxy is tilted, in degrees: at 0 it is seen face on, at 80 almost edge on.
SPINscript.js1How fast it turns while it works.
FAIL_EVERYscript.js2One render in how many, started by hand, loses its render node: 0 never.
FAIL_ATscript.js0.46How far into the render the node is lost, from 0 to 1.
TOURscript.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.
PHASESscript.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.
LABELSscript.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.
WORDSscript.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.

Try them in the Playground

When to use it

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.

On phones

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.

With reduced motion

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.

Pitfalls

  • The fragment shader would not start: the same uDust uniform was highp in the vertex shader and mediump in the fragment one, and WebGL rejects the program. It is now declared mediump in both.
  • The first attempt moved every star from the cloud to its orbit by angle, taking the difference between the two: when the turning orbit passed over the cloud’s angle the difference jumped by a whole turn and the star leapt. Now the star goes in a straight line, and an extra rotation that is zero at the start and at the end gives it its spiral.
  • A canvas that has been asked for WebGL no longer gives a 2D context: for the fallback (also when the context is lost) a fresh one is made and takes the old one’s place.
  • With the cloud as big as the galaxy its left and right edges were cut by the fade at the edge of the canvas and the cloud looked like a rectangle: it is now more gathered, in clumps, and stars past radius 0.84 are drawn gently back in.
  • In the finished tick the short and the long strokes were white and flat: six thousand stars on a short line burnt out in added light. 58% of the stars now go to the ring and their light in the tick is less than half, so the blend from violet to peach shows.
  • The galaxy formed too late (halfway through the render there was only the core): the thresholds at which each star settles and the winding of the arms now start earlier, and the arms read from about a third.
  • The title went red before its words changed (for a moment, Rendering your scene in red): the colour is now an attribute of the line, set together with the new words.
  • With time capped at 1/30 of a second a frame, on a slow computer the demo’s render takes longer: that is on purpose (no jumps), but the preview’s round must be counted at 60 frames a second.

Libraries

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.

Testing

Tested on 17 October 2026

  • Desktop: Done
  • Phone: Done
  • Reduced motion: Done
  • Safari on iPhone: To do

License

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.

All components