Skip to content
animorio
IT
All components

The yarn ball download

Loading, 3D, PhysicsCanvas, GSAPAdvancedCompressed weight: Demo 16 KBGSAP 28 KBFreeDownload the zip

The download of a design kit as a strand of yarn that comes in from the left, taut and swinging, and winds onto a ball that spins and grows with the bytes. Every pass is a great circle on a sphere at a new slant, drawn in 3D on a canvas with the back half hidden. If the connection drops the strand snaps and hangs from the ball until Retry; at the end the cut end tucks under, the ball gives a little hop and rolls a short way.

The code

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 yarn ball download</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/anybody@5.3.0/standard.css">
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <main class="stage">
    <!-- the download of a design kit shown as a strand of yarn: it comes in from the left, taut and swinging, and is
         wound onto a spinning ball that grows with the bytes. Every pass of yarn is a great circle on a sphere, tilted a
         little more each time, drawn in 3D on the canvas. The words, the figure and the button are HTML -->
    <section class="kit" aria-labelledby="kit-title" data-kit>
      <div class="kit__head">
        <div class="kit__words">
          <h2 class="kit__title" id="kit-title"><span class="kit__swap" data-title>Field Kit</span></h2>
          <p class="kit__meta"><span class="kit__swap" data-meta>Fonts, icons &amp; textures · v2.4</span></p>
        </div>
        <p class="kit__figure" aria-hidden="true">
          <span class="kit__pct is-quiet" data-pct>312 MB</span>
          <svg class="kit__tick" viewBox="0 0 24 24" data-tick><path d="M5.5 12.6l4.1 4.1L18.6 7.4" pathLength="1"/></svg>
        </p>
      </div>
      <div class="kit__ball" role="progressbar" aria-labelledby="kit-title" aria-valuemin="0" aria-valuemax="100"
           aria-valuenow="0" aria-valuetext="Not downloading" data-bar>
        <canvas class="kit__paint" aria-hidden="true" data-paint></canvas>
      </div>
      <div class="kit__foot">
        <p class="kit__note"><span class="kit__swap" data-note>1,208 files</span></p>
        <button class="pill" type="button" data-action data-autoclic><span class="pill__label" data-label>Download</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.

28 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 yarn ball download” from Animorio and fit it into my site

What it does

On a black background, alone in the middle, a charcoal panel with round corners: at the top Field Kit and Fonts, icons & textures · v2.4, on the right 312 MB; in the middle a small coral yarn ball resting on the panel, with its shadow, and a strand that comes in from the left edge and touches it at the top, a little slack; below, 1,208 files and the pale Download button. Pressed, the strand is pulled taut with a jerk and rings; then the bytes arrive and the ball starts spinning to take it up: the strand runs (you see the plies travelling towards the ball), swings with every chunk that lands and the ball grows pass after pass, each at a new slant, with the passes behind hidden and the ones underneath darker. At the top the percentage climbs, the line says how many megabytes have arrived and how long is left, below is the speed; the button becomes Pause, outlined. Paused, the strand goes slack and the ball stops (Resume). One time in two, in the demo, the connection drops halfway: the strand snaps, the half on the edge's side is whipped away out of the panel and the other half falls and hangs down the side of the ball to the panel, its end frayed; the title says Download interrupted in red and the button becomes Retry. Retry brings the strand back in from the left, the hanging half rises, the two ends join and the download goes on from where it stopped. At the end the cut end runs in, the ball winds it on and tucks it under the last pass, gives a little hop, squashes as it lands and rolls a short way to the right; a tick is drawn in place of the percentage and the title says Field Kit is ready. Download again shrinks the ball, the strand comes back and it starts over with a different winding.

How it works

One strand on a sphere

The ball is a single curve worked out once: a point p and its heading t walk along a great circle (p' = p cos ds + t sin ds, t' = t cos ds − p sin ds). At the end of every pass, a little longer than one turn so that the passes do not all cross at one place, the heading turns about p towards the next of a set of slants spread over the whole sphere (a golden spiral), by at most TILT degrees: so every pass is a new great circle and the ball gets covered all over instead of in a band.

The radius goes with the cube root

The ball's volume grows with the yarn wound on, and the yarn with the bytes: the radius of every pass is the cube root of r0³ + (R³ − r0³) · s / N. Every pass lies on a sphere a little larger than the one before, so the old ones stay under the new ones in the drawing too.

The winding is what spins the ball

Every frame the script finds where the strand coming from the edge touches the ball (the tangent from a point to a circle) and builds the rotation M = S·Eᵀ that brings the end of the curve exactly there, heading back along the strand and a little towards the viewer. The more yarn arrives, the further the end of the curve moves and the more the ball turns: no made-up spinning speed.

Back, core, front

The projected curve is drawn in stretches: first the hidden half of the last passes, dark, from the newest to the oldest; then the core, a disc with a radial gradient as big as the passes of a few turns ago; then the front half from the oldest to the newest, so every pass covers the ones before. Every stretch has one dark outline under the whole piece (no joints), a body lit from the sphere's normal and darker the deeper it is buried, plies drawn as a dash that stays put on the yarn and a highlight on the newer passes. It is repainted only while something moves.

The taut strand, the snap and the hanging rope

The incoming strand is a straight line with a little sag plus three damped modes of vibration (sines of one, two and three half waves): the tension sets their frequency, big chunks of bytes and the first jerk strike them, the ball's turning makes them quiver. When the connection drops the strand becomes two Verlet ropes with length constraints, gravity, the panel as a floor and the ball as an obstacle: one is pulled out through the edge, the other hangs from the ball and rests on it. Retry brings the strand back in and puts the rope back on the taut line.

For those who cannot see it and those who want no motion

The ball is a role=progressbar with aria-valuenow and an aria-valuetext in megabytes, the panel has aria-busy while it downloads and an aria-live line says when the download starts, pauses, breaks off and ends. The button changes its word (Download, Pause, Resume, Retry, Download again) and the pill takes the new width with a bounce; a click from a script, the preview's, never pauses.

Values to change

NameFileDefaultWhat it changes
SECONDSscript.js6How long the demo download takes, in seconds (a real one follows its bytes).
SIZEscript.js312The package's megabytes.
PACKAGEscript.js'Field Kit'The package's name.
FAIL_EVERYscript.js2In the demo, one download in how many breaks off (0 never).
FAIL_ATscript.js0.57How far the download that breaks off gets, from 0 to 1.
BALLscript.js46The radius of the finished ball, in pixels.
THREADscript.js3.4How thick the yarn is, in pixels.
PASSESscript.js96How many passes of yarn make the whole ball.
TILTscript.js70By how many degrees at most each pass tilts from the one before.
SWINGscript.js1How much the incoming taut strand swings: 0 not at all, 1.5 a lot.
FOLLOWscript.js0.4How long the ball takes to catch up with the bytes, in seconds.

Try them in the Playground

When to use it

For a download or an export of a few seconds that has a name and a size: a font kit, an icon pack, a project archive. The growing ball says «it is piling up» better than a bar, and the snapped strand says at once that the connection dropped; for a half second load it is too much.

On phones

The panel takes the screen's width less 32 pixels (358 on a 390 screen) and keeps its height; the ball stays at 60% of the width and the strand gets shorter. The canvas paints at the screen's real density, up to twice. Under a finger the button squashes and springs back; its words widen on the width axis only under the mouse.

With reduced motion

No jerks, swinging, whipping, hops or rolling: the strand is taut or slack without ringing, the ball grows following the bytes at once (it is what says how far along things are), the snapped strand already hangs still, at the end the cut end is already wound in, and the tick and the new words fade in.

Pitfalls

  • With an outline and a body for every little piece of yarn, the round outline of each piece showed over the body of the one before and the yarn looked like a string of sausages: now there is one outline for the whole stretch, and only the body changes colour piece by piece.
  • With every pass's slant picked at random, nearby passes stayed close and the ball had a large smooth gap on one side: every pass now heads for the next slant of a golden spiral on the sphere, and the ball gets covered all over.
  • With 34 passes the yarn covered little more than half the sphere and the core showed as a smooth ball: the area sum (length times thickness against 4πR²) asked for about three times as much yarn, so 96 passes, drawing only the last 52 because the others are buried.
  • The piece of snapped yarn left on the ball was thrown over the top by the recoil and lay there, not looking broken: the recoil is now light and the piece is half the strand long, so it falls down the side to the panel.
  • The half of the strand on the edge's side, left to hang, dropped straight down the panel's edge, half outside: it is now pulled away out of the panel, and on Retry the strand comes back in from the left with its frayed end first.

Libraries

GSAP 3.15.0, Anybody (font variabile) 5.3.0.

Compressed with gzip, the three demo files weigh 16 KB; the libraries: GSAP 28 KB.

Testing

Tested on 8 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