Skip to content
animorio
IT
All components

The taut wire switch

Toggles, Physics, SVG, TextGSAPAdvancedCompressed weight: Demo 8.6 KBGSAP 28 KBFreeDownload the zip

The Do not disturb switch of a focus app, in the minimal style: the track is a hairline of wire stretched between two posts, and the knob is a bead threaded on it. The bead’s weight bends the wire; turned on, the bead runs to the far end, goes a pixel past and back, and the wire rings and settles. Beside it the word Off thins out and fades, On comes in thin and takes weight.

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 taut wire switch</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/archivo@5.3.0/wdth.css">
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <main class="stage">
    <!-- the Do not disturb switch of a focus app: the track is a hairline of wire stretched between two posts, and the
         knob is a bead threaded on it. The bead's weight bends the wire; sliding along, it drags the bend with it, and
         when it lands the wire rings and settles. The word next to it takes weight as the bead travels -->
    <div class="dnd" data-dnd>
      <label class="dnd__name" id="dnd-name" for="dnd-switch" data-name>Do not disturb</label>
      <div class="dnd__row">
        <button class="wire" id="dnd-switch" type="button" role="switch" aria-checked="false" aria-labelledby="dnd-name" data-switch data-autoclic>
          <svg class="wire__art" aria-hidden="true" focusable="false" data-art>
            <line class="wire__post" data-post></line>
            <line class="wire__post" data-post></line>
            <path class="wire__line" data-line></path>
            <g class="wire__bead" data-bead>
              <circle class="wire__ball" data-ball></circle>
              <circle class="wire__ball wire__ball--on" data-ball-on></circle>
            </g>
          </svg>
        </button>
        <label class="dnd__state" for="dnd-switch" aria-hidden="true" data-state>
          <span class="dnd__word dnd__word--off" data-off>Off</span>
          <span class="dnd__word dnd__word--on" data-on>On</span>
        </label>
      </div>
    </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.

20 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 taut wire switch” from Animorio and fit it into my site

What it does

On a black background, top left, the words Do not disturb; below them, a grey wire as thin as a hair stretched between two white posts, and threaded on it a white bead. Beside it, on the right, the word Off in grey, light. The bead’s weight bends the wire into a faint V. As the page opens the two posts stand up, the wire draws itself from one to the other, the bead drops onto it from above and the wire catches it, gives and sways before it stops. Turned on (a click, a tap, Space, Enter or the right arrow) the bead runs to the other end on a spring: crossing the middle it sinks deeper, because the wire gives more there, and the bend of the wire follows it. Arrived, it goes a pixel past and comes back, and as it lands it plucks the wire, which rings a few times and settles. Meanwhile the bead turns orange and the word changes: Off loses weight, narrows and fades away upwards, On comes in thin and narrow from below, takes weight up to a full black, a little too much as it lands, and settles with the wire. Under the mouse the bead leans towards the other end; pressed, it gets heavier and sinks. It can be grabbed and dragged along the wire, up and down too: the wire pulls into a V under the finger and, let go, springs back and rings. A click on the name or on the word turns it on and off as well.

How it works

A real switch

It is a button with role switch and aria-checked, named by the words above it (aria-labelledby): Space and Enter turn it on and off, the right and left arrows set it on or off, and the name and the word beside it are labels for it, so they can be clicked. Inside there is a single SVG with the two posts, the wire (a path) and the bead, a group of two circles: white below and orange above, with an opacity that follows the bead along the wire.

The wire is a real string

The wire’s displacement is the sum of its first 48 modes, sin(n π x / L), each a damped oscillator driven by the bead’s weight at the point where it is. Still, the modes add up to exactly the V of a string under a point load, deepest in the middle (4 SAG a(L − a) / L²): that is why the bead, crossing, rides down a curve. The wire’s notes are n times TONE, a touch sharp as in a slightly stiff wire, and the higher ones die sooner.

The exact step

Every mode moves on with the exact solution of its equation over the step (1/240 of a second), not with Euler: the high notes, far faster than the screen, stay stable at any frame rate and follow the bead, the low ones ring. The sines of the 48 modes at the bead are worked out with the recurrence sin((n+1)θ) = 2 cos θ sin(nθ) − sin((n−1)θ); those of the 84 points of the drawing are in a table rebuilt on resize. In the path the bead’s point is put in exactly, so the bend is sharp.

The bead and the pluck

Along the wire the bead is a mass on a spring (SPRING) damped just under critical (DAMPING 0.82): over a hundred pixels of travel it goes about a pixel past. When it crosses its place it plucks the wire: every mode takes a kick of speed in proportion to sin(nθ) / n^1.5 and to the speed of arrival (RING), and the word takes a knock of weight on a soft spring of its own. Pressed, its weight becomes PRESS times; dragged, the weight is worked out to hold it at the height of the finger, and let go it goes back to 1: the wire springs back by itself, because the modes stayed where they were.

The word

Off and On are two words in the same place, in variable Archivo, and their axes follow the bead: Off goes from weight 320 to 120 and from width 100 to 70 as it fades away upwards, On from 130 to 760 and from width 70 to 100 as it comes in from below; to On’s weight the knock of the landing is added, which goes past and settles. Only what changes is written, and when wire, bead and word are still the loop takes itself off GSAP’s ticker.

Values to change

NameFileDefaultWhat it changes
TONEscript.js4.2The wire’s lowest note, in vibrations a second: higher, a tauter wire.
DECAYscript.js0.04How soon the wire stops ringing (the damping of its lowest note).
SAGscript.js5.5How far the bead’s weight bends the wire in the middle, in pixels.
SPRINGscript.js160How hard the spring pulls the bead to its end of the wire.
DAMPINGscript.js0.82How the bead stops: under 1 it goes a little past (0.82 is about a pixel).
RINGscript.js5How hard the bead plucks the wire as it lands, in pixels.
PRESSscript.js1.9How much heavier the bead gets under a finger or the mouse.
PULLscript.js13How far the bead can be pulled off the line, up or down, in pixels.
PEEKscript.js5How many pixels the bead leans towards the other end under the mouse.
WEIGHTscript.js[320, 760]The weight of the word Off and of the word On (100 to 900).

Try them in the Playground

When to use it

For a switch that asks for calm: Do not disturb, a focus mode, pausing notifications, the silent mode of an app for meditating, reading or writing. The wire settling says by itself that everything has gone quiet. It is a piece to set on its own, on an empty background, where it is noticed; in a long list of settings it is best used for one entry only.

On phones

Same size as on a computer, 184 by 56 pixels, and at 390 pixels everything fits with plenty of space around it; under 300 pixels the wire shortens to 156. A tap turns it on and off; as soon as the finger rests on it the bead gets heavier and sinks, as with the mouse. A dragged finger takes the bead along the wire and up and down: that is why the page does not scroll on the switch (touch-action: none), but it does around it. No leaning under the mouse, which a finger does not have.

With reduced motion

No springs and no ringing: the wire is drawn still with its bend, the bead fades out at one end and back in at the other already in its colour, and Off and On swap in a fade of three tenths of a second, each with its own weight. As the page opens everything fades in already in place. Pressing does not sink it and it cannot be dragged; clicks, taps and keys work as always.

Pitfalls

  • With Euler, even at steps of 1/240 of a second, the high modes (hundreds of vibrations a second) would blow up after a few frames: every mode moves on with the exact solution of the damped oscillator over the step, stable for any note and any step.
  • With the bead resting on the posts the wire would not bend at all (at its ends a string does not move): the resting places are at 20 and 80 per cent of the wire, where the weight shows.
  • Drawn only from the fixed points, the wire under the bead would be a round curve and the bead would seem to float on it: the bead’s point is put exactly into the path, and the bend is sharp.
  • The first landing on the wire, dropping 34 pixels from above, covered the words Do not disturb: the drop starts 15 pixels above the wire, inside the switch, and the bead fades in as it falls.
  • The library’s preview clicks with a fake click every 2.8 seconds: the fake click (isTrusted false, detail 0) plays a whole round in a GSAP timeline, on, the bead pulled down and let go, off, and the clicks that arrive during the round are ignored. Space and Enter make real clicks and turn it on and off as always.
  • Dragging up and down, a finger would move the page: on the switch touch-action is none, because the bead is pulled vertically as well.

Libraries

GSAP 3.15.0, Archivo (font variabile) 5.3.0.

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

Testing

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