Skip to content
animorio
IT
Back to the library

The billiard break

Physics, SVGGSAPAdvancedCompressed weight: Demo 15 KBGSAP 28 KBFreeDownload the zip

A billiard table seen from above: the cue aims with the pointer, draws back and breaks the rack with real physics. The balls really roll, the potted ones spin down a small whirl into the ball return, then the triangle puts everything back.

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 billiard break</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/fraunces@5.3.0/standard.css">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/mona-sans@5.3.0/standard.css">
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <main class="sala">
    <header class="testa">
      <p class="sopra">The Baize Room Billiard Club</p>
      <h1 class="titolo">Break the rack</h1>
      <p class="riga">Aim with the pointer: the farther away it is, the harder the cue hits. Click the table to shoot.</p>
    </header>

    <!-- the table is drawn by the script: felt, rails, pockets, fifteen numbered balls and the cue -->
    <div class="tavolo" data-tavolo>
      <svg class="tavolo__svg" data-svg role="img" aria-label="A billiard table seen from above, with fifteen balls racked in a triangle"></svg>
    </div>

    <div class="piede">
      <div class="conti">
        <p class="conto"><span class="conto__nome">Potted</span> <span class="conto__num" data-imbucate>0</span><span class="conto__su">/15</span></p>
        <p class="conto"><span class="conto__nome">Breaks</span> <span class="conto__num" data-colpi>0</span></p>
        <p class="stato" aria-live="polite"><span class="stato__testo" data-stato>Table is set</span></p>
      </div>
      <!-- the ball return: potted balls roll in here -->
      <div class="vassoio" data-vassoio aria-label="Ball return"></div>
      <button type="button" class="tiro" data-tiro data-autoclic>
        <span class="tiro__fondo" aria-hidden="true"></span>
        <span class="tiro__testo">Break</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.

41 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 billiard break” from Animorio and fit it into my site

What it does

On the table of an invented club, The Baize Room, with green cloth, wooden rails with their grain and mother-of-pearl diamonds, the wooden triangle comes down onto the foot spot, the fifteen numbered balls drop into it row by row with a bounce and the triangle, after a little nudge to tighten them, lifts away. In comes the cue, which follows the pointer: it turns smoothly, and the farther the pointer is from the cue ball the more it draws back, because the shot will be harder. A dashed line shows where the cue ball will go, with the ghost ball at the point of contact and the path of the ball it hits. On click the cue winds up, pauses for a moment and strikes: a little puff of blue chalk, the table shakes as the rack is hit and the balls scatter, bouncing off each other and the cushions, slowed down by the cloth. As they run they really roll: numbers and stripes turn on the ball. Those that reach a pocket spin down a small whirl, shrink and disappear, and a matching little ball rolls into the ball return under the table; the counter updates with a hop. When everything has stopped a line says how it went, then the triangle comes back, the balls left on the table roll to their places, the potted ones pop back up and the cue ball returns behind the line.

How it works

A small physics engine, written by hand

No libraries: for identical balls a few lines are enough. At every step the cloth takes away speed (a constant friction plus one that grows with speed), then every pair of touching balls is checked: they are separated and exchange the impulse along the line of centres, with a coefficient of restitution. There are as many steps as needed so that no ball moves more than a third of its radius: this way no ball passes through the others on the break.

Cushions and jaws as segments

Each cushion is a segment, and at the pockets it continues with two slanted segments, the jaws. For each ball the closest point of each segment is found: if it is closer than the radius the ball is pushed out and its velocity bounces along the normal. The same rule makes the bounces off the cushions and the balls that rattle on the pocket edge and stay out.

Balls that really roll

Each ball keeps two 3D vectors: the pole of the number and the axis of the stripe. When it moves by d, they rotate by d over the radius around the horizontal axis perpendicular to the motion. Number and stripes are caps of the sphere seen from above: their rim is sampled and the points behind the ball are pushed onto the outline, so every frame becomes an SVG path.

The cue and the shot

The cue is drawn once with its tip at zero and moves with a single transform: cue ball position, aim angle and distance. The angle chases the pointer with an exponential ease, and the distance tells the power. The shot is a GSAP timeline: wind-up, pause, sharp strike, and only at the end of the strike does the cue ball get its speed.

The whirl and the triangle

A potted ball leaves the physics and a GSAP timeline spirals it towards the centre of the pocket, the way it was running, while it shrinks and rolls. When everything has stopped, a delayedCall waits for the pause and then the triangle racks the balls again: there too every ball rolls as it goes back to its place.

Values to change

NameFileDefaultWhat it changes
POTENZAscript.js3400The cue ball’s speed on the hardest shot, in table units per second (the table is 1000 long).
ATTRITOscript.js270How much the cloth slows the balls: higher, the break ends sooner.
SPONDAscript.js0.78How much the balls bounce off the cushions (1 = losing nothing).
URTOscript.js0.95How elastic the collisions between balls are.
EFFETTOscript.js0.3Spin on the cue ball: positive follows on after the hit, negative draws it back.
PAUSAscript.js0.9Seconds to wait, with the balls still, before the triangle racks them again.
GUIDAscript.jstrueThe aiming line with the ghost ball.

Try them in the Playground

When to use it

For the page of a bar, a club or a game, a playable 404 page or a moment of fun inside a site: it is a toy, and belongs where visitors have time.

On phones

The table turns upright so it stays large. With no hover, a tap does it all at once: it aims at the finger and shoots, with the power given by the distance. The button shoots along the starting aim.

With reduced motion

No motion: the whole break is computed at once, the balls fade out and reappear where they stopped; the triangle racks them again with a fade too.

Pitfalls

  • With a single step per frame, on the break the cue ball covers more than a radius per frame and passes through the balls: steps must be split according to the fastest ball.
  • Slow balls must be really stopped below a threshold (here 6 units per second): with proportional friction alone the speed drops without ever reaching zero and the end of the shot never comes.
  • Straight cushions with pockets as plain circles leave balls circling in the corner without dropping: you need slanted jaws, and a check that pots any ball that leaves the table anyway.
  • The cue follows the cue ball: if after the shot it keeps reading its position, it chases it across the table. Freeze the starting point at the strike.
  • In SVG text turns with the table: when the table is turned upright the numbers must be counter-rotated, or they read sideways.

Libraries

GSAP 3.15.0, Fraunces (font variabile) 5.3.0, Mona Sans (font variabile) 5.3.0.

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

Testing

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