Skip to content
animorio
IT
All components

The tick ring chart

Charts, Hover, Physics, TransitionsCanvas, GSAPAdvancedCompressed weight: Demo 9.4 KBGSAP 28 KBFreeDownload the zip

A month of spending in a ring of 120 thin ticks, like a watch face, in the minimal style: every category is an arc of ticks. Moving over a category, on the ring or in the key, its ticks grow one after another on staggered springs and take the accent, the others shorten, and in the middle the figure counts with the running digits heavier and narrower.

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 tick ring chart</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/roboto-flex@5.3.0/full.css">
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <main class="stage">
    <!-- a month of spending drawn as a dial of thin radial ticks: every category is an arc of ticks. Pointing at a
         category (on the ring or in the key) its ticks grow one after another on staggered springs and turn the
         accent, the others shorten, and the figure in the middle counts to its amount. The ring is drawn by the
         script on a canvas; the key carries the numbers for screen readers -->
    <section class="spend" aria-label="Spending by category" data-spend data-autoclic>
      <div class="spend__ring" data-ring>
        <canvas class="spend__canvas" aria-hidden="true" data-canvas></canvas>
        <div class="read" aria-hidden="true">
          <span class="read__label" data-label></span>
          <span class="read__amount" data-amount></span>
          <span class="read__note" data-note></span>
        </div>
      </div>

      <ul class="key" role="list" aria-label="Categories" data-key></ul>

      <p class="sr" aria-live="polite" data-said></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.

33 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 tick ring chart” from Animorio and fit it into my site

What it does

On a black background, on the left a ring of thin radial ticks, on the right the key. The ticks are 120 places around the circle, starting at the top and going clockwise: every spending category of October (Rent, Savings, Food, Travel, Bills, Leisure) takes as many as its share of the month, with two empty places between one category and the next, and has its own grey, from the lightest for the largest to the darkest for the smallest. In the middle: October, the total $4,220 and spent this month. When the page opens the ticks grow round from the top and the total counts up from zero; the key comes in row by row, and under every entry a thin rule grows as long as its share. Moving the pointer over an arc of the ring, or over an entry in the key, that category's ticks grow one after another in a wave that starts under the pointer (from the key it starts at the arc's first tick), overshoot by a pixel and settle, and turn orange; the others shorten and go dark. On the thin circle inside the ticks an orange arc opens, in the middle the name rolls up in place of October, the figure counts to the category's spending and under it comes its share (39% of October). While the figure counts, every digit that is changing grows heavier and narrower, and settles when it stops: the first to stop are the ones on the left. Leaving, everything goes back to rest in a wave.

How it works

The ticks, counted right

The categories share the 120 places minus the gaps with the largest remainder method, so the ticks always add up and every category has at least one; with the same method the key's percentages add up to 100. Every tick has a place, a category and a length, as a part of the ring's width: on resize it is simply drawn again.

A spring per tick, tied together

Every tick is a damped spring (SPRING) towards its goal length, worked out in steps of 1/240 s on GSAP's ticker, with the step held to 1/30 s. It also pulls its neighbours (PULL) by how far each is from its own goal: the wave has a body, the ticks next to it feel the knock, and two neighbours with different goals both still get there.

The staggered wave

Choosing a category, every tick gets its new goal with a delay proportional to its distance (round the ring) from the starting point: STAGGER seconds per tick for the ones growing, a quarter of that for the ones shortening. The length decides everything else: the colour turns from the category's grey to the accent in a narrow band, so a tick is grey or orange and crosses the mix quickly, and the stroke grows by half a pixel.

The figure in tabular digits

Every sign of the figure sits in a box of its own, the same width for all digits, counted from the right: so a digit growing heavier or narrower never moves its neighbours. When a digit changes it heats up (wght plus HEAT, wdth minus 14) and cools on a spring: the digits on the left stop first and settle first.

It stops when it is still

The loop only runs while something moves and stops when every tick is at its goal, the digits are cool and the tweens are over: at rest the canvas is not drawn again.

Keys, fingers and the preview

The key's entries are buttons with aria-pressed and the arrows, Home and End go from one to the next; Esc goes back to the total, and a line for screen readers reads category, spending and share. A finger taps an arc or an entry, and tapping it again, or outside, goes back to the total. A click from a script (the library's preview) goes round every category in a GSAP timeline, back to rest, and again.

Values to change

NameFileDefaultWhat it changes
TICKSscript.js120How many ticks make the ring, gaps included.
GAPscript.js2The empty ticks between two categories.
STAGGERscript.js0.016The seconds between one tick and the next in the wave.
SPRINGscript.js[320, 0.56]Each tick's spring: how stiff, and how much it is held back (1 = no overshoot).
PULLscript.js0.22How much a tick pulls its neighbours, as a part of its stiffness.
LENGTHSscript.js[0.075, 0.15, 0.04]A tick's length at rest, chosen and dimmed, as a part of the ring's width.
HEATscript.js300How much weight a running digit takes (the figure is 520).
ARRIVALscript.js1.1The seconds the ticks take to grow all the way round when the page opens.
MONTHscript.js'October'The month the figure in the middle adds up.
CURRENCYscript.js'$'The sign before the figures.
SPENDINGscript.js[{ name: 'Rent', amount: 1650 }, …]The categories and what went into each (up to ten).

Try them in the Playground

When to use it

For a household or budgeting app, a bank's monthly summary, the costs of a trip or a project, a shop's dashboard with sales by department: wherever a total splits into a few parts.

On phones

The key goes under the ring, in two columns, and the ring takes the width of the screen up to 340 pixels. A finger taps an arc or an entry to choose it, and tapping it again or outside goes back to the total: the same waves as on a computer.

With reduced motion

The ticks are already in place and change length at once, with the ring fading back in; the figure changes without counting and without changing weight, the words in the middle swap with a fade.

Pitfalls

  • With the shares rounded one by one the ticks do not add up to 120 and the percentages do not add up to 100: both are counted with the largest remainder method.
  • Tabular digits keep the same width only at a fixed weight and width: with wght and wdth changing digit by digit the figure wobbled. Every sign sits in a box of fixed width, counted from the right.
  • A tick tied to its neighbours with the classic spring (towards their average) never reaches its goal where two categories meet: the push is worked out on how far each one is from its own goal.
  • The colour mixed linearly between grey and orange gave salmon ticks halfway through the wave: the change happens in a narrow band of the length, on a soft curve.
  • The two words in the middle swapping together covered each other for a moment: the new one starts when the old one has gone.

Libraries

GSAP 3.15.0, Roboto Flex (font variabile, assi wght, wdth e opsz) 5.3.0.

Compressed with gzip, the three demo files weigh 9.4 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