Skip to content
animorio
IT
All components

The ring timer

Timers, SVG, PhysicsGSAPAdvancedCompressed weight: Demo 7.4 KBGSAP 28 KBFreeDownload the zip

A tea timer set by turning the knob round the ring, as on a kitchen timer: the arc follows it on a spring and the figures roll; started, the arc runs round the whole ring and empties as the time goes by, and when it is up the ring rings, shaking like a bell and throwing out rays.

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 ring timer</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/urbanist@5.3.0/index.css">
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <main class="stage">
    <!-- the ring timer: the time is set by turning the knob round the ring (or with a kind of tea), runs down as the
         arc shrinks back, and rings when it is up -->
    <div class="timer" data-timer data-autoclic>
      <div class="dial" data-dial>
        <svg class="dial__art" viewBox="0 0 320 320" aria-hidden="true" data-art>
          <circle class="dial__track" cx="160" cy="160" r="130"/>
          <g class="dial__ticks" data-ticks></g>
          <path class="dial__arc" data-arc/>
          <g class="dial__rays" data-rays></g>
        </svg>
        <div class="dial__knob" role="slider" tabindex="0" aria-label="Time" aria-valuemin="5" aria-valuemax="300" data-knob></div>
        <div class="dial__face">
          <span class="dial__time" data-time></span>
          <span class="dial__label" data-label></span>
        </div>
      </div>
      <div class="teas" role="group" aria-label="Kinds of tea" data-teas></div>
      <div class="controls">
        <button class="ctl ctl--ghost" type="button" aria-label="Start over" data-reset>
          <svg viewBox="0 0 24 24" aria-hidden="true"><path d="M5.5 9A7.5 7.5 0 1 1 4.6 14M5 4.5V9h4.5"/></svg>
        </button>
        <button class="ctl ctl--main" type="button" aria-label="Start" data-go>
          <svg viewBox="0 0 24 24" aria-hidden="true"><polygon data-shape/><polygon data-shape/></svg>
        </button>
      </div>
      <p class="sr" aria-live="polite" data-live></p>
    </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.

18 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 ring timer” from Animorio and fit it into my site

What it does

On a black background a dark ring with sixty ticks (longer every five), a matcha arc starting at the top and covering two fifths of it with a white knob at its end, and in the middle 2:00 and Green tea; under it, three teas, Green tea 2:00 lit, Black tea 4:00 and Herbal 5:00, a round button to start over and a big matcha play button. Dragging the knob round the ring, or pressing on the ring, the time changes five seconds at a time: the arc follows on a spring, the ticks under it light up, the figures roll each in its own window and the knob nods at every step; a tea sets its time and the arc runs there. With play the sign folds into pause, the knob draws back and the arc runs round the whole ring, then goes back towards the top as the time passes, with the figures going down second by second. Pause, start over. At zero the dial shakes like a bell, rays fly out of the ring twice, the figures flash and Ready appears; then it goes back to the time set and the knob comes back.

How it works

The arc and the knob

The arc is an SVG path from the top, with the large-arc-flag once it is past half (and two half arcs when it is whole); its length is a share of the ring that a spring (SPRING) brings to the right value, worked out on GSAP’s ticker in steps of 4 milliseconds. While setting, the share is the time on the dial’s scale (MAX seconds a whole turn); started, it is the share of the time left, so on starting the arc runs on to the whole ring. The knob sits at the end of the arc, placed by GSAP (x and y), and nods with scale at every step.

Turning the knob

The angle from the middle to the pointer becomes seconds, rounded to STEP. Crossing the top the angle would jump by a whole turn: the difference from the angle before is corrected by a turn and the hand is held at the ends (no jump from 5:00 to 0:05).

The figures

Every figure has its own window (overflow hidden): when it changes, the new one comes from above if the time goes down, from below if it goes up, and the old one leaves the other way; a roll still going ends at once, so fast turns never pile up.

The sign and the ring

Play and pause are two four-sided shapes (the two halves of the triangle, the two bars) whose corners move. When the time is up the dial turns with rotation keyframes for RING seconds, sixteen rays (lines) fly out twice, lengthening and fading, and the figures flash (opacity in yoyo).

Keys and the preview

The knob is a slider (role slider): the arrows by STEP, Page Up and Down by a minute, Home and End to the ends, Enter or space start and stop; an aria-live region says started, paused, time is up. A click from a script (the library’s preview) turns the knob down to a few seconds and starts, then chooses a tea, starts, pauses and starts over, and leaves a short countdown alone until it has rung.

Values to change

NameFileDefaultWhat it changes
MAXscript.js300The seconds of a whole turn of the dial.
STEPscript.js5How many seconds the knob moves by.
TEASscript.js[['Green tea', 120], ['Black tea', 240], ['Herbal', 300]]The teas: name and seconds.
SPRINGscript.js[220, 0.8]The arc’s spring as it follows the hand or a tea: how stiff it is and how much it is held back.
RINGscript.js1.4The seconds the dial rings when the time is up.

Try them in the Playground

When to use it

For a kitchen or tea timer, a rest between two sets at the gym, work and break times, a countdown in a game or for an offer.

On phones

The dial takes up to 82 per cent of the width and the knob turns under a finger: on the dial the page does not scroll (touch-action none) while it is turned.

With reduced motion

The arc goes straight where it should, without spring or sweep, the figures change without rolling, the sign changes at once; when the time is up the dial does not shake or throw out rays: it says Ready and goes back to the time set.

Pitfalls

  • An SVG arc made of a single A command does not draw the whole circle (start and end are the same point): when the arc is full, two half arcs are drawn.
  • The angle from atan2 jumps by a whole turn crossing the top: the difference from the angle before is used, corrected by a turn, and the hand is held at the ends.
  • If GSAP moves an element (the knob’s nod, with scale), its place must go through GSAP too (x and y, here with quickSetter): a transform written by hand and GSAP’s cancel each other out.
  • A few seconds on a five-minute scale make an arc you can hardly see: started, the arc becomes the share of the time left and runs round the whole ring.

Libraries

GSAP 3.15.0, Urbanist (font variabile) 5.3.0.

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

Testing

Tested on 3 October 2026

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

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