Skip to content
animorio
IT
Back to the library

The blocks that count pi

PhysicsGSAPMediumCompressed weight: Demo 6.7 KBGSAP 28 KBFreeDownload the zip

In the minimal style, with exact physics: on a black page a small block waits between a wall and a big block sliding towards it. The knocks are perfectly elastic, with no friction, and a large serif number counts them: with equal masses there are 3, with a block a hundred times heavier 31, ten thousand times 314. They are the first digits of pi, which light up in orange at 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>Counting pi</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/fraunces@5.3.0/full.css">
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <!-- the whole room is the button: a click brings the next pair of blocks -->
  <main class="stage" data-stage tabindex="0" role="button" aria-label="Two blocks slide into a wall and count their collisions: the counts are the digits of pi. Press for the next pair.">
    <header class="top">
      <span class="top__brand">Quanta</span>
      <span class="top__note">A physics lecture series, season two</span>
    </header>

    <div class="count" data-count-box>
      <p class="count__value" data-count>0</p>
      <p class="count__label">collisions</p>
      <p class="pi" data-pi aria-label="pi is 3.14159265">
        <span class="pi__name">π =</span> <span data-digits>3.14159265</span>
      </p>
    </div>

    <svg class="room" data-svg aria-hidden="true">
      <g data-hatch></g>
      <path class="wall" data-wall d="" />
      <path class="floor" data-floor d="" />
      <rect class="block block--small" data-small x="0" y="0" width="0" height="0" />
      <rect class="block block--big" data-big x="0" y="0" width="0" height="0" />
      <text class="mass" data-mass-small x="0" y="0">1 kg</text>
      <text class="mass" data-mass-big x="0" y="0">1 kg</text>
    </svg>

    <p class="hint" data-hint>Click for the next pair of blocks.</p>
    <p class="read" data-readout><span class="read__label">Mass ratio</span> <b class="read__value" data-read>1 : 1</b></p>
  </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.

21 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 blocks that count pi” from Animorio and fit it into my site

What it does

A black page, at the top the name of an invented series of physics lectures, Quanta. The floor, a thin line, draws itself from the wall to the right; the wall rises with its short hatches behind it, as in a technical drawing; under a large serif nought appear collisions and the line π = 3.14159265. Two blocks drawn with a single line come in, with their mass written below in italics: a small one resting near the wall and an equal one further away, which sets off and slides towards the small one. They touch: the big one stops, the small one goes to the wall, comes back, gives the push back to the big one, and both leave the room. At every knock the number at the top goes up by one and gains weight for an instant, and the small block lights up in orange. When the knocks are over the number, 3, turns orange and the first digit of pi lights up. Then a new pair comes in: the big block weighs a hundred times the small one, and the small one goes back and forth thirty-one times between the wall and the big one, which slows down, stops and goes back; 3.1 lights up. Last the big one weighs ten thousand times more: the small one buzzes between the wall and the big one, ever closer, the counter runs up to 314 and 3.14 lights up. Then it starts again. Bottom right you read the ratio of the masses. A click brings the next pair at once.

How it works

The physics, knock by knock

There is no fixed step: inside every frame the script works out how long until the small block reaches the wall and how long until it reaches the big one, moves both blocks to the first of the two moments, makes the knock and starts again, until the frame is over. Against the wall the small block's speed changes sign; between the two blocks the elastic knock keeps momentum and energy. So even the three hundred knocks of the ten-thousand pair, crowded into a few pixels, are exact, and the count is always 314.

Why the digits of pi come out

Put the speeds of the two blocks on a plane, with the axes scaled by the square root of the masses: the energy is a circle and every knock is a bounce between two lines, whose angle is the arctangent of the square root of the mass ratio. With a ratio of 100 to the power n, the number of bounces that fit in half a turn is the first n plus one digits of pi. The script stops counting when both blocks move to the right and the big one is faster: they can never touch again.

The number that feels the knocks

The counter is set in Fraunces, a variable serif, at optical size 144 and weight 300. Every knock adds a little weight that fades by itself within a tenth of a second: when the knocks crowd together, the number grows bolder and trembles with them. When the count is done the number turns orange and the digits of pi the count has found light up one after another.

The direction

Every pair is a GSAP timeline: the blocks fade in, the number goes back to nought and the big block sets off at the speed that brings it onto the small one in SPEED seconds. A gsap.delayedCall holds the result for HOLD seconds, then the blocks fade and the next pair comes in. A frame's time never goes over a thirtieth of a second, and when nothing moves the page is not redrawn.

Values to change

NameFileDefaultWhat it changes
RATIOSscript.js[1, 100, 10000]How many times heavier the big block is, one pair after another. Powers of 100 give the digits of pi; a million gives 3141 knocks, very crowded.
SPEEDscript.js0.9How many seconds the big block takes to reach the small one.
HOLDscript.js2.4How many seconds the result stays before the next pair.
UNITscript.js'kg'The unit written under the blocks.
--accentstyle.css#ff5a1fThe colour of the small block’s knocks and of the digits found.

Try them in the Playground

When to use it

For a page that tells an idea at a glance: a lecture series or a science festival, a museum, the blog of a science writer, the cover of a physics or maths course, the about page of a studio that loves numbers. The large number works as the title.

On phones

The same physics, exact on every screen: the wall sits near the edge, blocks and distances are measured on the width, the number is larger in proportion. A tap brings the next pair.

With reduced motion

Nothing slides: each pair's count is already done (the script works it out silently), the blocks sit in their places and the number is already orange with its digits of pi lit. A click moves to the next pair with a fade.

Pitfalls

  • A fixed step, even a small one, would miscount the ten-thousand pair: towards the end the knocks between the wall and the big block fall fractions of a millisecond apart, and two would land in the same step. That is why the calculation goes knock by knock, with no step, and the count is exact.
  • The loop only comes back on itself after about twenty-five seconds (three pairs): the card's video must take all of them, or it stops after the first.
  • On the phone the wall's hatches went below the floor: the last one is only drawn if it ends above the line.

Libraries

GSAP 3.15.0, Fraunces (font variabile) 5.3.0.

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

Testing

Tested on 19 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 animations