
L’indicatore a lancetta
Contatori, Fisica, SVG
NuovaGratis
La tessera fedeltà di una piccola torrefazione, di cartoncino color crema, con dieci chicchi di caffè stampati: a ogni caffè la foratrice si porta via il chicco successivo. La card si piega sotto la pressione verso quel chicco e torna su passando di un pixel; il pezzetto di carta esce dal retro, lo vedi cadere attraverso il suo stesso buco, nell’ombra della card, e uscire rigirandosi da sotto il bordo. In ogni buco si vede la pagina con l’ombra vera della card. Undo lo fa risalire e lo rimette nel buco; piena, la tessera prende il timbro Redeemed e al tocco dopo ne arriva una nuova.
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 punch card</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/bricolage-grotesque@5.3.0/standard.css">
<link rel="stylesheet" href="style.css">
</head>
<body>
<main class="stage">
<!-- the loyalty card of a small coffee roaster, on paper. Every cup bought the card is punched: the punch
bites a coffee bean out of it, the card dips under the press and springs back, and the little paper bean
falls out of the back of the card, seen through its hole, and tumbles out from under it. Through every hole
you see the page, with the card's own shadow in it. Full, the card is redeemed with a stamp, and a fresh one
takes its place. The paper, the beans and the stamp are drawn by the script and the CSS -->
<div class="loyalty" data-loyalty>
<div class="chads" aria-hidden="true" data-chads></div>
<div class="deal" data-deal>
<div class="tilt" data-tilt>
<button class="card" type="button" data-card data-autoclic aria-describedby="loyalty-status">
<svg class="paper" viewBox="0 0 320 420" aria-hidden="true" data-paper>
<defs>
<mask id="loyalty-holes" maskUnits="userSpaceOnUse" x="-10" y="-10" width="340" height="440">
<rect x="-10" y="-10" width="340" height="440" fill="#fff" />
<g data-holes></g>
</mask>
</defs>
<g mask="url(#loyalty-holes)">
<rect class="paper__sheet" width="320" height="420" rx="16" />
<rect class="paper__frame" x="10.5" y="10.5" width="299" height="399" rx="9" />
<path class="paper__rule" d="M24 238.5H296" />
<g data-beans></g>
<g class="stamp" data-stamp>
<rect class="stamp__box" x="-88" y="-27" width="176" height="54" rx="6" />
<rect class="stamp__box stamp__box--in" x="-82" y="-21" width="164" height="42" rx="3" />
<text class="stamp__word" y="-1">Redeemed</text>
<text class="stamp__date" y="13" data-stamp-date>19 Oct 2026</text>
</g>
</g>
</svg>
<span class="card__words">
<span class="card__brand">Halde</span>
<span class="card__kind">Coffee roasters · Loyalty card</span>
<span class="card__headline" data-headline>Ten cups, the eleventh is on us.</span>
<span class="card__status" id="loyalty-status"><span class="card__num" data-num>Four</span><span data-rest> cups to go</span></span>
<span class="card__small">Valid at both Halde counters</span>
</span>
<span class="sr" data-label>Punch a cup</span>
</button>
<button class="undo" type="button" data-undo hidden>
<svg viewBox="0 0 16 16" aria-hidden="true"><path d="M5.5 4.5 2.5 7.5l3 3M3 7.5h6.5a3.5 3.5 0 0 1 0 7H8" /></svg>
<span>Undo</span>
</button>
</div>
</div>
<p class="hint" aria-hidden="true" data-hint>Press the card to punch a cup</p>
<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.
26 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 «La card della tessera da forare» da Animorio e adattala al mio sitoLa tessera è un SVG di 320 × 420: il cartoncino, il filetto, i chicchi stampati e il timbro stanno in un gruppo con una mask, e ogni buco è un ovale nero nella maschera. Forare vuol dire accendere quell’ovale: il taglio è netto a ogni misura, e i chicchi stampati sotto il taglio si nascondono, perché il pezzo se li porta via.
L’ombra non è un box-shadow ma due drop-shadow sul cartoncino già tagliato: una stretta che disegna il bordo di ogni buco e una morbida che dice quanto è alta la tessera. Siccome si calcolano sulla forma tagliata, dentro ogni buco cade da sola la mezzaluna d’ombra del cartoncino, e quando la tessera si alza la mezzaluna cresce.
La pressione e il sollevamento sono due molle integrate sul ticker di GSAP in quattro sotto-passi col passo limitato a 1/30 di secondo (SPRING). La pressione gira la tessera in 3D verso il chicco di turno (rotateX e rotateY in proporzione alla sua posizione, PRESS gradi) e la spinge indietro; al rilascio torna su oltre il riposo e oscilla. Un tasto o un clic dello script fanno pressione e rilascio in un colpo solo, con una spinta alla molla.
Ogni pezzo tagliato è un piccolo SVG in uno strato sotto la tessera: parte esattamente dietro il suo buco, quindi si vede solo attraverso il buco, in ombra, mentre si rimpicciolisce un poco allontanandosi. Ha gravità (GRAVITY), una spinta di lato, una rotazione e un giro su se stesso fatto con scaleY = cos dell’angolo: quando il coseno è negativo mostra il retro del cartoncino. Sotto il bordo esce dall’ombra e svanisce in trenta pixel.
Undo riprende il pezzo da dove si trova (o da sotto il bordo, se è già caduto) e con una timeline lo riporta al buco rigirandolo al dritto; quando arriva il buco si chiude e la tessera riceve un colpetto. Il timbro scende con power4.in, la tessera sobbalza all’impatto e il timbro si assesta con un elastico; la tessera nuova arriva con back.out.
La tessera è un button: Invio e Spazio forano, riscattano o chiedono la tessera nuova, Undo è un button suo e Ctrl o Cmd+Z fanno lo stesso. Il focus da tastiera alza la tessera e mostra il chicco di turno come il passaggio del mouse; al telefono il dito la piega dove forerà. Un aria-live dice quanti caffè mancano.
| Nome | File | Di partenza | Cosa cambia |
|---|---|---|---|
CUPS | script.js | 10 | Quanti caffè riempiono la tessera, in due file (da 6 a 12). La frase in alto si scrive da sola. |
PUNCHED | script.js | 6 | Quanti caffè sono già forati quando si apre la pagina. |
PRESS | script.js | 5 | Quanto si piega la tessera sotto la foratrice, in gradi. |
SPRING | script.js | [260, 0.36] | La molla della tessera: quanto è rigida e quanto è frenata (1 = senza rimbalzi). |
GRAVITY | script.js | 1600 | Quanto in fretta cade il pezzetto forato, in pixel al secondo quadrato. |
LIFT | script.js | 5 | Quanto si alza la tessera col puntatore sopra, in pixel. |
SLANT | script.js | -14 | L’inclinazione dei chicchi stampati, in gradi. |
Per la tessera fedeltà di un bar, di una torrefazione, di una gelateria, di un panificio o di un parrucchiere, nell’app o nel sito dove il cliente vede i suoi punti; anche per una raccolta di bollini, un abbonamento a ingressi o un pass da dieci lezioni.
La tessera è larga 320 pixel, o lo schermo meno 32, e tutte le scritte sono in unità del contenitore, così restano al loro posto a ogni misura. Col dito la tessera si piega dove forerà, al rilascio fora; Undo ha un’area di tocco di 36 pixel. Molle, caduta e tempi sono quelli del computer.
Niente piega, niente sollevamento e niente pezzetti che cadono: il buco compare con una dissolvenza, Undo lo richiude allo stesso modo, il numero cambia con una dissolvenza, il timbro appare piano e la tessera nuova arriva in dissolvenza.
GSAP 3.15.0, Bricolage Grotesque (font variabile) 5.3.0.
Compressi con gzip, i tre file della demo pesano 9,5 KB; le librerie: GSAP 28 KB.
Provata il 19 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.