
Il rullo delle ore
Selettori, 3D, Fisica
NuovaGratis
Il Checkout · €48.00 di un negozio come un registratore di cassa smaltato d'altri tempi: nella pillola color sangue di bue, filettata d'oro, una tastiera di nove tasti in tre colonne costruita in CSS 3D, sopra un'insegna dorata con la finestrella del totale, sotto il cassetto. Al clic i tasti del totale si abbassano uno dopo l'altro e tornano su con la loro molla, le bandierine 4, 8 e 00 saltano su nella finestrella oscillando sul loro perno, la molla del cassetto lo spinge fuori, batte sul fermo e rimbalza, e la scritta diventa Paid · Order 4821. Un altro clic richiude il cassetto con un tonfo e le bandierine ricadono.
Una cartella che funziona da sola: index.html, style.css, script.js e le librerie da CDN. Nelle schede React e Vue la stessa demo è già un componente, che spegne le sue animazioni quando esce dalla pagina.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>The cash register button</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/mona-sans@5.3.0/wdth.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/big-shoulders-display@5.3.0/wght.css">
<link rel="stylesheet" href="style.css">
</head>
<body>
<main class="stage">
<!-- the cash register button: the Checkout of a shop as an enamelled cash register of the old days. In the pill a
bank of keys in columns, over it the window where the amount flags come up, under it the cash drawer. A click
rings the total up: the keys go down one after the other on their springs, the flags with the total jump up
in the window, the drawer is kicked out and bounces on its stop, and the pill says Paid with the order number.
Another click pushes the drawer shut and the register is back at rest -->
<div class="till" data-till>
<div class="till__unit">
<!-- the drawer under the pill: the tray with the notes and the coins, and its front -->
<div class="till__drawer" aria-hidden="true" data-drawer>
<div class="till__slide" data-slide>
<svg class="till__tray" viewBox="0 0 170 40" preserveAspectRatio="none" data-tray></svg>
<div class="till__front">
<span class="till__pull"></span>
</div>
</div>
</div>
<div class="till__body" data-body>
<!-- the sign over the pill: a gilt frame, and behind its glass the flags of the amount -->
<div class="till__sign" aria-hidden="true">
<span class="till__crest">Amount</span>
<span class="till__window" data-window>
<span class="till__mark">€</span>
<span class="till__slot" data-slot="tens"><span class="till__flag" data-flag="tens">4</span></span>
<span class="till__slot" data-slot="units"><span class="till__flag" data-flag="units">8</span></span>
<span class="till__mark till__mark--dot">.</span>
<span class="till__slot till__slot--wide" data-slot="cents"><span class="till__flag" data-flag="cents">00</span></span>
</span>
</div>
<button class="till__btn" type="button" data-btn data-autoclic>
<span class="till__fill" aria-hidden="true"></span>
<!-- the keys: three columns of three, built in CSS 3D by script.js -->
<span class="till__bed" aria-hidden="true">
<span class="till__bank" data-bank></span>
</span>
<span class="till__faces">
<span class="till__face" data-face="rest">
<span class="till__word" data-wide="Checkout · €48.00" data-rest-text>Checkout · €48.00</span>
</span>
<span class="till__face" data-face="busy" aria-hidden="true">
<span class="till__quiet" data-busy-text>Ringing up…</span>
</span>
<span class="till__face" data-face="done" aria-hidden="true">
<span class="till__paid" data-paid-text>Paid</span>
<span class="till__sep">·</span>
<span class="till__order" data-order-text>Order 4821</span>
</span>
</span>
</button>
</div>
</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>Cambia valori, colori e testi con le manopole e guarda l’animazione rispondere dal vivo. Oppure scrivi tu nel codice. Poi scarica la cartella con le tue modifiche.
30 valori da cambiare
Col connettore di Animorio, Claude Code la prende da qui con tutta la sua guida e la adatta al tuo progetto. Incolla questa richiesta:
Prendi «Il pulsante del registratore di cassa» da Animorio e adattala al mio sitoUn piano largo 76 pixel è girato di rotateX(52deg) dentro un incavo con perspective: 190px, così i tasti si vedono un poco dall'alto e quelli in fondo sembrano più lontani. Ogni tasto è una pila di otto dischi con transform-style: preserve-3d: un'ombra sfocata sul piano, quattro dischi stretti per lo stelo, due anelli di nichel (un gradiente conico) e la faccia di celluloide con la cifra. Ogni disco sta a translateZ(var(--h) · var(--f)), dove --f è la sua frazione dell'altezza: lo script scrive solo --h per tasto, e premendo la pila si schiaccia tutta insieme, con lo stelo che sparisce sotto la faccia.
Chrome dipinge un livello in 3D alla misura che ha prima della trasformazione: i tasti costruiti a 16 pixel venivano sgranati e le cifre si leggevano male. Ora i tasti sono costruiti quattro volte più grandi (64 pixel, cifre a 29) dentro un contenitore con scale3d(0.25, 0.25, 0.25) e anche le altezze sono moltiplicate per quattro: lo scale3d rimpicciolisce anche l'asse Z, così la prospettiva resta quella giusta e le facce escono nitide a ogni densità di schermo.
L'altezza di ogni tasto è una molla: h'' = ω² · (H0 − TRAVEL · press − h) − 2 · ζ · ω · h', con ω = 2π · 9 e ζ = KEY_BOUNCE. GSAP muove solo press, il dito: scende in 75 millisecondi con power2.in, resta giù un attimo e si alza di colpo; è la molla a riportare su il tasto, che passa il suo posto e torna. Il piano non si attraversa: sotto 0,6 pixel il tasto si ferma. Al passaggio del puntatore ogni tasto riceve una piccola velocità, colonna per colonna a 45 millisecondi l'una dall'altra, e trema sulla sua molla.
Ogni bandierina sta in una fessura con overflow: hidden e perspective: 60px, nascosta sotto il bordo con translateY(105%). Quando il suo tasto tocca il fondo, l'obiettivo della sua molla (ω = 2π · 5,5, smorzamento 0,26) passa a 1 e riceve una spinta: sale, va un poco oltre e si ferma. Mentre sale si inclina sul perno con rotateX proporzionale alla sua velocità, così sembra montata su un'asta e non su una guida. Le cifre vengono da TOTAL: decine, unità e centesimi; i tasti di ogni colonna sono la cifra che serve e due vicine, così cambiando il totale nel Playground la tastiera e le bandierine si rifanno da sole.
Il cassetto è un vassoio in SVG (banconote negli scomparti, monete nelle coppette, l'ombra sotto il registratore) e un frontale smaltato, dentro un contenitore con overflow: hidden che comincia sotto la pillola. La molla lo spinge con una forza che cala mentre si apre, 2600 · KICK · (1 − x / (1,6 · OPEN)), e le guide lo frenano un poco; a OPEN pixel batte sul fermo e torna indietro col 38% della velocità, due o tre volte. Ogni colpo dà una spinta alla molla verticale del registratore, che sobbalza. Al primo colpo la pillola dice Paid e il numero d'ordine. Per chiuderlo un tween power2.in lo riporta a zero, poi il tonfo: il registratore salta, il fondo della pillola si schiaccia e le bandierine ricadono, dai centesimi alle decine.
Tre facce sovrapposte larghe quanto le parole (Checkout · €48.00, Ringing up…, Paid · Order 4821), la pillola misurata una volta sulla più larga. Il pulsante è un button vero con aria-disabled mentre i tasti battono e il cassetto si apre o si chiude, una zona aria-live che dice Ringing up…, poi Paid. Order 4821, €48.00. e infine Drawer closed, e da aperto un aria-label che dice Close the drawer. Battere il totale e aprire il cassetto dura circa 1,5 secondi, meno dei 2,8 fra due clic dell'anteprima: un clic apre, quello dopo chiude, e ogni vendita prende il numero d'ordine seguente. Il loop di fisica dorme quando tutto è fermo e nessun tween sta lavorando.
| Nome | File | Di partenza | Cosa cambia |
|---|---|---|---|
LABEL | script.js | Checkout | La scritta a riposo, prima del totale. |
TOTAL | script.js | 48 | Il totale in euro, da 0,01 a 99,99: la tastiera mette in ogni colonna la cifra che serve e due vicine, e le bandierine mostrano il totale. |
BUSY | script.js | Ringing up… | La scritta mentre i tasti battono; la dice anche la zona aria-live. |
PAID | script.js | Paid | La parola in oro quando il cassetto è fuori, prima del numero d'ordine. |
ORDER | script.js | 4821 | Il numero del primo ordine: ogni vendita prende il seguente. In un sito vero è il numero che il tuo server dà all'ordine. |
KEY_GAP | script.js | 0.3 | I secondi fra un tasto e il successivo. |
TRAVEL | script.js | 6 | Quanto scende un tasto premuto, in pixel (un tasto è alto 9). |
KEY_BOUNCE | script.js | 0.18 | Come tornano su i tasti: 0,05 rimbalzano a lungo, 0,18 passano il loro posto e tornano, 1 salgono senza passarlo. |
KICK | script.js | 1 | Quanto forte la molla spinge fuori il cassetto: 0,5 scivola fuori, 2 sbatte sul fermo e rimbalza di più. |
OPEN | script.js | 34 | Quanto esce il cassetto, in pixel: più esce, più si vede del vassoio. |
Per il pulsante che chiude un acquisto: il Checkout o il Pay di un negozio online, la cassa di un'app per i negozi, un caffè o un mercato con un'identità d'epoca, una pasticceria, un barbiere, un negozio di dischi. Va collegato a un pagamento vero: qui il pagamento è simulato, e in un sito vero il cassetto si apre quando il server conferma l'ordine.
La pillola è larga circa 280 pixel, con l'insegna sopra e il cassetto sotto: a 390 pixel ci sta con margine. Il tocco fa tremare i tasti, schiaccia il fondo e batte il totale; un altro tocco chiude il cassetto. I tasti restano della loro misura e nitidi anche a densità 3.
I tasti non si muovono: la faccia di quello premuto si scalda d'oro e torna avorio. Le bandierine compaiono in dissolvenza già al loro posto, il cassetto sparisce chiuso e riappare aperto in dissolvenza, senza rimbalzi né sobbalzi, e le scritte arrivano in dissolvenza. La pillola non si gonfia e la scritta non si allarga (sotto il mouse il fondo si schiarisce appena). Il clic dopo chiude allo stesso modo.
GSAP 3.15.0, Mona Sans (font variabile) 5.3.0, Big Shoulders Display (font variabile) 5.3.0.
Compressi con gzip, i tre file della demo pesano 12 KB; le librerie: GSAP 28 KB.
Provata il 10 ottobre 2026
Puoi usarla nei tuoi progetti e in quelli dei tuoi clienti. Non puoi rivenderla né ridistribuirla così com’è. GSAP resta sotto la sua licenza Standard. Licenza completa.
Con l’email e la password del tuo account.
oppure con l’email
Hai fatto l’accesso come .
Con l’account scarichi lo zip di ogni animazione e di ogni pacchetto, gratis.