Skip to content
animorio
IT
All components

The gumball machine button

Buttons, Physics, HoverCanvas, GSAPAdvancedCompressed weight: Demo 15 KBGSAP 28 KBFreeDownload the zip

The Add to cart of a candy shop, with a small gumball machine standing in the round end of the pill: a glass globe full of coloured gumballs, a red enamel body, a chrome knob and a chute that runs down into a pocket sunk in the pill. The gumballs are rigid bodies in a real simulation on a canvas: they fall, knock into each other and against the glass. Over the button the globe shakes a little and the gumballs settle again. At a click the knob turns half round, the lowest gumball drops into the body, comes out on the chute, rolls, hops off the small lip at its end and lands in the pocket: the counter rolls to Added · 1 in cart. Every click drops another one; at the limit Clear shows up, and it throws the gumballs back into the globe through the open lid.

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 gumball machine button</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/mona-sans@5.3.0/wdth.css">
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <main class="stage">
    <!-- the gumball machine button: the Add to cart of a candy shop, with a small gumball machine standing in the round
         left end of the pill. The gumballs are round rigid bodies in a real simulation on a canvas: gravity, knocks
         against each other and against the glass. Over the button the globe shakes a little and they settle again. A
         click turns the knob: one gumball drops out of the globe, rolls down the chrome chute, hops into the cup in the
         pill, and the counter rolls up. At the limit, Clear sends them back into the globe -->
    <div class="gum" data-gum>
      <canvas class="gum__art" aria-hidden="true" data-art></canvas>
      <button class="gum__btn" type="button" data-btn data-autoclic>
        <span class="gum__fill" aria-hidden="true"></span>
        <span class="gum__faces">
          <span class="gum__face" data-face="rest">
            <span class="gum__word" data-label-text>Add to cart</span>
            <span class="gum__price" data-price-text>€6.90</span>
          </span>
          <span class="gum__face gum__face--busy" data-face="busy" aria-hidden="true">
            <span class="gum__shine" data-busy-text>Adding…</span>
          </span>
          <span class="gum__face gum__face--done" data-face="done" aria-hidden="true">
            <span class="gum__done">
              <span data-done-text>Added</span>
              <span class="gum__dot">·</span>
              <span class="gum__roll" aria-hidden="true"><span class="gum__digits" data-digits><span>0</span><span>1</span><span>2</span><span>3</span><span>4</span><span>5</span><span>6</span><span>7</span><span>8</span><span>9</span></span></span>
              <span data-cart-text>in cart</span>
            </span>
            <span class="gum__chip" data-chip data-clear-text>Clear</span>
          </span>
        </span>
      </button>
      <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.

32 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 gumball machine button” from Animorio and fit it into my site

What it does

On a white background a dark cocoa pill 60 pixels tall, with a thread of light along the top and a soft shadow under it. In its left end stands a small gumball machine a little over a hundred pixels tall: the glass globe with its crescent of reflection at the upper left, a sharp point of light, the window reflected on its right side and a thin dark line on its rim; above it the red domed lid with its chrome knob; below it the collar and the red enamel body, wider at the foot, with its stripe of light, the chrome plate of the knob with its bar and its coin slot, and on the right side the little door a chrome chute comes out of. The chute runs down into the pill to a sunken pocket, dark at the bottom and fading out towards the top. In the globe twelve gumballs of eight colours, each a sphere painted with its light at the upper left, its shaded side, its darker rim and the light bounced back from below. Right of the pocket, in cream Mona Sans, Add to cart · €6.90. On arrival the lid is open and the gumballs rain in one after the other, bounce off the glass and each other and settle; then the lid shuts with a bounce. With the mouse over the machine or the pill the globe shakes a little, the gumballs lift a hair and drop back into place; over the pill the words widen and the fill swells with a bounce. At a click the words become Adding… with a sheen running through them, the knob turns half round with a small knock the gumballs feel, and the lowest gumball sinks through the hole of the globe pushing its neighbours, which fall to fill the gap. It comes out of the little door onto the chute, rolls down faster and faster, the lip at the end makes it hop, and it drops into the pocket, where it bounces and stops. At that moment the pill narrows to Added · 1 in cart, with the number on a small drum. Every click drops another one, which lands on the others in the pocket, and the drum rolls to 2, 3, 4. At the fourth the pill stretches with a bounce and a small Clear pill shows up: the next click opens the lid and the gumballs in the pocket fly one after the other in an arc into the globe, which shuts again; the words go back to Add to cart · €6.90. With the keyboard the focus shows a ring and the globe shakes; Enter or Space add. On a phone a touch shakes the globe and adds.

How it works

The gumballs as rigid bodies

Each gumball is a circle of radius 5 with a position and a speed. Every frame (capped at 1/30 of a second) is worked out in steps of 1/240: GRAVITY, a breath of air drag, then three rounds of constraints. Two gumballs touching are pushed apart by half each and, if they are coming together, trade an impulse along the line between their centres with a BOUNCE, plus a little friction across it. Under 40 pixels a second the bounce is zero: so a pile rests instead of trembling.

The moving glass

The gumballs in the globe live inside a circle: if they get out they are put back on the rim and their speed relative to the glass loses its outward part. The glass's own speed counts, because the globe shakes (a GSAP timeline of six keyframes on its offset): the glass coming in pushes the gumballs near it, and with a small random lift they are seen to settle. The same knock, smaller and vertical, comes when the knob turns.

The gumball that drops

At a click the gumball lowest down and nearest the middle is picked. It becomes kinematic: GSAP takes it to the hole and down into the body, and in collisions it has infinite mass, so it pushes its neighbours instead of being stopped by them. Inside the body it is hidden by the drawing (the globe's gumballs are drawn before the collar and the body); then it is born again on the chute with a speed, and from there it is a free body again, drawn only right of the little door.

The chute and the pocket

Outside the globe the gumballs meet segments: the chute (with a small upturned lip at its end, which makes it hop) and the pocket, a U of two walls and fourteen segments of arc. Contact with a segment finds the nearest point, puts the gumball back one radius away and takes off its speed into the wall. When the gumball passes the pocket's lip it has arrived: the number's drum turns and the pill changes its words. If it has not arrived after 2.4 seconds, it is set in the pocket.

The arc home

At Clear the lid opens round its left hinge and each gumball in the pocket follows a quadratic curve from its place to the hole at the top: a quadratic Bézier walked at an even pace is exactly the path of a throw. Once there it becomes a body of the globe again with its arriving speed and bounces off the others. The gumballs are sprites painted once per colour at the screen's density; the loop stops when none of them moves any more.

The words and the states

Three faces on top of each other, as wide as their words and measured to the fraction of a pixel: at rest, busy, and the count with its drum (a column of digits moved in yPercent with back.out). The machine never moves: the component keeps its width at rest and the pill grows or shrinks to the right. The button is a real button, aria-disabled while the gumball drops, with an aria-live region saying Added. 2 in cart. and an aria-label giving the count; a click on the machine adds too.

Values to change

NameFileDefaultWhat it changes
LABELscript.jsAdd to cartThe words at rest; they widen under the pointer.
PRICEscript.js€6.90The price beside the words.
BUSYscript.jsAdding…The words while the first gumball rolls down.
DONEscript.jsAddedThe word before the count.
CARTscript.jsin cartThe words after the count.
CLEARscript.jsClearThe small pill that shows up at the limit: its click empties the cart.
LIMITscript.js4How many gumballs go in the cart before Clear (1 to 5: the pocket holds five).
GUMBALLSscript.js12How many gumballs there are in the globe.
GRAVITYscript.js1800How fast they fall, in pixels a second squared: lower, a slow fall as on the moon.
BOUNCEscript.js0.35How much they bounce: 0 they land dead, 0.7 they bounce a long time.
SHAKEscript.js1.6How far the globe shakes under the pointer, in pixels: 0 it stays still.

Try them in the Playground

When to use it

For the Add to cart of a sweet shop, a pick and mix store, a toy or gadget shop, or any site with a playful tone: the machine says one more please better than an icon. It also suits the quantity counters of a children's catalogue or a bakery. Adding is simulated here: in a real site the count comes from your server's cart.

On phones

The component is about 300 pixels wide at rest and about 340 with Clear: at 390 pixels it fits. A touch shakes the globe and adds a gumball; the machine keeps the same size.

With reduced motion

The gumballs are already still in the globe, with no rain on arrival and no shaking; the pill does not swell and the words do not widen. At a click a gumball in the globe fades out and one fades in already resting in the pocket, and the count fades in. Clear fades out those in the pocket and brings back those in the globe.

Pitfalls

  • The gumballs going home stayed still in the pocket: the helper that keeps the loop awake during a tween put its own onUpdate in place of the one moving the gumball along its arc. Now it calls both.
  • The component was centred on the page, so when the pill widened or narrowed the machine slid sideways. Now the box keeps its width at rest and the pill grows only to the right.
  • With the invisible copy of the wide words (the trick that keeps the pill's size under the pointer) a gap was left between Add to cart and the price. Now the room for the widening is measured once and left at the end of the pill, with the transition switched off while measuring: otherwise the old width was read.
  • A pile of gumballs trembled forever: each step's gravity turned into a small bounce. Under 40 pixels a second the bounce is zero, and the loop sleeps when all of them are under 6 pixels a second.
  • For the pocket, a shape with a slanted top edge looked like a black drop: now it is a U that fades into the pill towards the top, with the thread of light only round its bottom.

Libraries

GSAP 3.15.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 12 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