Skip to content
animorio
IT
All components

The desk fan switch

Toggles, Physics, TransitionsCanvas, GSAPAdvancedCompressed weight: Demo 13 KBGSAP 28 KBFreeDownload the zip

The Desk fan switch of a smart home app, and the knob is the fan. Turned on, the blades get up to speed and blur into a disc, and three curled paper ribbons hidden behind the knob unroll like a party blower and flap along the track. Turned off, the fan winds down by itself and the ribbons roll back up from the end.

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">
  <title>The desk fan switch</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/rethink-sans@5.3.0/index.css">
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <main class="stage">
    <!-- the switch of a desk fan in a smart home app. The knob is the fan: turned on, its blades get up to speed and
         blur into a disc, and three curled paper ribbons tied behind it unroll in the air and stream along the track;
         turned off, the fan winds down on its own and the ribbons spring back into their curls -->
    <div class="fan" data-fan>
      <label class="fan__label" for="fan-switch" data-label>Desk fan</label>
      <button class="fan__switch" id="fan-switch" type="button" role="switch" aria-checked="false" data-switch data-autoclic>
        <span class="fan__fill" aria-hidden="true" data-fill></span>
        <canvas class="fan__air" aria-hidden="true" data-air></canvas>
        <canvas class="fan__air fan__was" aria-hidden="true" data-was></canvas>
        <span class="fan__shade" aria-hidden="true"></span>
        <span class="fan__knob" aria-hidden="true" data-knob>
          <span class="fan__puck" data-puck>
            <canvas class="fan__rotor" data-rotor></canvas>
          </span>
        </span>
      </button>
    </div>
  </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.

26 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 desk fan switch” from Animorio and fit it into my site

What it does

On a white background the words Desk fan and next to them a light grey pill switch with a big white knob: inside the knob the five grey blades of a fan, with the hub in the middle. Turned on, the knob snaps to the other end and bounces a little, the track turns azure and the blades get up to speed: at first you can see them turn, then they blur into a pale blue disc, like a real fan running. When the fan is at half speed, three white paper ribbons come out from behind the knob, curled up like the ribbon on a present: the air unrolls them from the knot to the end, one after the other, like a party blower, and then they flap along the track, turning in the wind and now and then showing their pale blue back. Turned off, the knob goes back and the motor lets go: the blades slow down by themselves, fast at first and then slower and slower, and the disc turns to brushed steel before it is five still blades again. The last breath pushes the ribbons out on the other side, and as soon as the fan drops below half speed they roll back up from the end to the knot, behind the knob. Under the mouse the knob leans towards the other side and the still blades turn a little, as if they felt the hand coming; pressed, it gets smaller; it can be dragged too, and the fan runs the faster the farther along it is taken. A click on the words turns it on and off as well.

How it works

A real switch

It is a button with role switch and aria-checked, with its own label for: Enter and Space turn it on and off, so does a click on the words, and its name for screen readers is the words. Inside are the colour of the track when on (its opacity follows the knob), two canvases for the ribbons (the second one is for the reduced motion fade), a layer with the track’s inner shadow, and the knob: an element that runs and inside it a disc that squashes, with the canvas of the blades.

The motor and the blur

The fan’s speed goes from 0 to 1: the motor pulls it to 1 in SPIN_UP seconds; let go, the air brakes it with the square of the speed and the bearings with a steady friction, so from full speed it stops in COAST seconds, fast at first and slowly at the end. The blades are drawn up to 32 times over the angle they turn in a sixtieth of a second, each with 1/32 of white added in lighter mode: only how much of each pixel they cover is added up, and the colour goes on afterwards with source-in. At a steady speed that picture does not change, it only turns: it is worked out again only when the blur changes by 0.02 radians, and every frame it is laid down turned to the angle of the fan.

The ribbons

Each ribbon is a chain of points every 5.5 pixels (Verlet), tied to the middle of the fan. Every frame it takes six steps: the air pushes each piece of paper across with the square of the relative speed and drags it along, more gently, keeping it taut; a spring bends every joint towards its curl, stiff where the ribbon is still rolled up and soft where it is open; then three rounds of constraints hold the length and keep the paper inside the track. The air leaves the fan towards the free part of the track, slows down as it goes and comes in gusts: waves about sixty pixels long that travel with it.

The party blower

For every ribbon a number says how far the air has unrolled it, from the knot (0) to the end (1): past that front the joints are still rolled up. Above 42 per cent of the speed the front moves on (one ribbon a moment after the other); below half it goes back, and the end rolls up first. The rolled part travels with the knob, tucked behind it, and the knot sits a little higher, so the roll stays in the middle. The gusts and the turning of the paper come only once the ribbon is open.

The paper and the knob

The ribbon is drawn as a strip as wide as it is, narrower where it turns its edge to you and bluer where it shows its back: the turn follows a cosine that travels with the air, and the colour is a gradient along the track. The knob is a mass on a spring (SPRING) with two walls: it bounces (BOUNCE) and squashes on the wall’s side. Dragged past 5 pixels it captures the pointer and runs the fan as fast as how far along it is; let go, a fast flick decides by its direction, otherwise the half it is in. When everything is still and rolled up the ribbons stop being worked out and drawn.

Values to change

NameFileDefaultWhat it changes
SPEEDscript.js16How fast the fan turns at full speed, in turns a second.
SPIN_UPscript.js0.9The seconds the motor takes to get the fan up to speed.
COASTscript.js2.4The seconds the fan takes to stop by itself once it is turned off.
BLADESscript.js5The blades of the fan.
SHUTTERscript.js1How much of a sixtieth of a second the eye holds: the blur of the running blades (0, no blur).
WINDscript.js300How fast the air goes at full speed, in pixels a second.
GUSTSscript.js0.5How much the air comes in gusts and flaps the ribbons (0, a steady breeze).
RIBBONSscript.js[84, 98, 72]The ribbons tied behind the fan: how long each one is, in pixels.
CURLscript.js0.16How tight the ribbons curl up when the air stops: one over the radius of the curl.
SPRINGscript.js170How hard the spring pulls the knob to its end of the track.
BOUNCEscript.js0.3How much of its speed the knob keeps bouncing off the end (0, no bounce).
PEEKscript.js4How far the knob leans towards the other side under the mouse, in pixels.

Try them in the Playground

When to use it

For the switch of a device that moves or does something you can see: a fan, an air purifier, the ventilation of a house or a car, the fan of a laptop. The blades and the ribbons say by themselves what the switch is for, and the fan winding down by itself says it does not stop at once. In a list of devices it is best used for one only, next to plain switches.

On phones

Same size as on a computer, 156 by 56 pixels, and at 390 pixels the words and the switch still sit on one line. A tap turns it on and off; a finger dragged sideways takes the knob along and runs the fan, while up and down the page still scrolls (touch-action: pan-y). No leaning under the mouse, which a finger does not have. On a 120 hertz screen the blur is the same, because it is worked out over a sixtieth of a second and not over the frame.

With reduced motion

No movement: on, the fan is a still picture of itself running, the blurred disc with the ribbons stretched out in the wind; off, five still blades and no ribbons. At a click the knob fades out at one end and back in at the other, the colour of the track changes in a fade and the old picture of the ribbons fades away over the new one, in under half a second. Pressed, it does not get smaller and cannot be dragged; clicks and keys work as always.

Pitfalls

  • Adding up the coloured blades in lighter mode, each with 1/16 of the ink, tinted the grey disc green and lilac while the fan slowed down: every pass rounds the three 8 bit channels differently and the errors add up. Now only the coverage is added up, in white, and the colour goes on afterwards with source-in.
  • The weight of the paper unrolled the root of the curl and the roll hung down to the bottom of the track, peeking out under the knob: the rolled paper is stiffer, and the knot sits 8 pixels higher while the ribbon is rolled up.
  • The ribbons opened while the knob was still bouncing and turned into a tangle; and the curls swung out above the knob as it ran. Now they unroll only above 42 per cent of the speed, once the knob has arrived, one after the other, the gusts come only once a ribbon is open, and the rolled part travels with the knob.
  • Turning off, the knob ran over the ribbons and crumpled them against the end: the rolling back, the best moment, happened out of sight. Now the fan always blows towards the free part of the track, and the ribbons roll back up only below half speed: the last breath takes them to the right of the knob, and there the curl can be seen coming back.
  • The gusts were waves 38 pixels long going by at 255 pixels a second: the paper moved by 2 pixels and the ribbons looked like spaghetti. Now the waves are about sixty pixels long and stronger, and the open paper is softer.
  • Drawing the blades 16 times every frame cost 1.2 milliseconds: at a steady speed the blurred disc is always the same picture turned, and now it is worked out once and laid down turned. The roll behind the knob trembled by a tenth of a pixel forever and never came to rest: the rolled paper has a friction of its own, and when everything is rolled up and still within half a pixel the ribbons stop.

Libraries

GSAP 3.15.0, Rethink Sans (font variabile) 5.3.0.

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

Testing

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