
Gli oggetti senza peso
Fisica, 3D, Hover
NuovaGratis
Due dadi veri in CSS 3D lanciati da un bicchiere di cuoio: rotolano sul panno con la fisica vera, rimbalzano, si urtano fra loro e contro la sponda e si fermano su una faccia. La somma arriva in grande con un rimbalzo.
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>Dice on the table</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/fraunces@5.3.0/full.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/instrument-sans@5.3.0/wdth.css">
<link rel="stylesheet" href="style.css">
</head>
<body>
<main class="stage">
<!-- the dice night of a made-up board game bar. On the left the name and the roll; on the right a felt table seen
from above, with a walnut rail, two dice and a leather cup. The dice, their faces and their shadows are built
by the script -->
<section class="side">
<header class="brand">
<svg class="brand__mark" viewBox="0 0 40 40" aria-hidden="true">
<rect x="5" y="5" width="30" height="30" rx="8" transform="rotate(-12 20 20)"/>
<circle cx="14.5" cy="15" r="2.6"/><circle cx="20" cy="20" r="2.6"/><circle cx="25.5" cy="25" r="2.6"/>
</svg>
<p class="brand__name">Pip & Felt<span>Board game bar</span></p>
</header>
<div class="score" data-score>
<div class="score__intro" data-intro>
<p class="score__kicker">Thursday dice night</p>
<h1 class="score__title">Roll for the house round</h1>
</div>
<div class="score__result" data-result aria-hidden="true">
<p class="score__kicker" data-name>Natural seven</p>
<p class="score__sum"><span data-sum>7</span></p>
<p class="score__parts" data-parts>4 + 3</p>
</div>
</div>
<p class="sr" role="status" aria-live="polite" data-said></p>
<div class="actions">
<button class="roll" type="button" data-roll data-autoclic>
<span class="roll__fill" aria-hidden="true"></span>
<span class="roll__label" data-roll-label>Roll the dice</span>
</button>
<p class="rule">House rule: doubles buy the next round.</p>
</div>
</section>
<div class="scene" data-scene>
<div class="jolt" data-jolt>
<div class="table" data-table>
<div class="rail" aria-hidden="true"></div>
<div class="felt" aria-hidden="true"><span class="felt__print">Pip & Felt</span></div>
<div class="wall wall--back" aria-hidden="true"></div>
<div class="wall wall--front" aria-hidden="true"></div>
<i class="anchor" data-anchor></i>
<i class="anchor" data-anchor></i>
</div>
</div>
<div class="cup-place" data-place>
<div class="cup" data-cup>
<svg viewBox="0 0 120 150" aria-hidden="true">
<defs>
<linearGradient id="dt-leather" x1="0" x2="1">
<stop offset="0" stop-color="var(--leather-dark)"/>
<stop offset="0.3" stop-color="var(--leather-light)"/>
<stop offset="0.55" stop-color="var(--leather)"/>
<stop offset="1" stop-color="var(--leather-dark)"/>
</linearGradient>
<linearGradient id="dt-band" x1="0" x2="1">
<stop offset="0" stop-color="var(--leather-deep)"/>
<stop offset="0.32" stop-color="var(--leather-dark)"/>
<stop offset="1" stop-color="var(--leather-deep)"/>
</linearGradient>
<radialGradient id="dt-mouth" cx="0.5" cy="0.2" r="0.8">
<stop offset="0" stop-color="#140b06"/>
<stop offset="1" stop-color="#3a2012"/>
</radialGradient>
</defs>
<path class="cup__body" d="M6 18 Q8 90 15 140 Q60 152 105 140 Q112 90 114 18 Z" fill="url(#dt-leather)"/>
<path d="M9 40 Q60 52 111 40 L110.6 52 Q60 64 9.3 52 Z" fill="url(#dt-band)"/>
<path d="M13.5 118 Q60 130 106.5 118 L105.6 130 Q60 142 14.4 130 Z" fill="url(#dt-band)"/>
<path class="cup__stitch" d="M10 45 Q60 57 110 45"/>
<path class="cup__stitch" d="M14.5 123.5 Q60 135.5 105.5 123.5"/>
<path class="cup__seam" d="M88 24 Q89 80 92 138"/>
<path class="cup__stitch" d="M85 26 Q86 80 89 136"/>
<g class="cup__crest">
<rect x="44" y="72" width="26" height="26" rx="6" transform="rotate(-12 57 85)"/>
<circle cx="51.5" cy="80" r="2"/><circle cx="57" cy="85" r="2"/><circle cx="62.5" cy="90" r="2"/>
</g>
<ellipse cx="60" cy="18" rx="54" ry="12" fill="url(#dt-mouth)"/>
<path class="cup__rim" d="M6 18 A54 12 0 0 0 114 18 A54 12 0 0 0 6 18 Z"/>
<path class="cup__shine" d="M24 30 Q26 80 30 128"/>
</svg>
</div>
</div>
<p class="hint" data-hint>Tap the table to throw</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.
36 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 «I dadi sul tavolo» da Animorio e adattala al mio sitoOgni dado è un div con transform-style: preserve-3d e sei facce spinte fuori di mezzo lato con translateZ, girate con rotateX e rotateY. I puntini stanno in una griglia di tre per tre, con un’ombra interna che li fa sembrare scavati. Gli angoli arrotondati lascerebbero dei buchi agli spigoli: dentro il dado ci sono tre piani color avorio scuro, uno per asse, che li riempiono e fanno da smusso. Il dado vive dentro il tavolo, inclinato con rotateX, quindi l’alto per lui è l’asse z del tavolo.
Ogni dado ha posizione, velocità, orientamento (un quaternione) e rotazione. A ogni passo la gravità lo tira giù; se uno degli otto spigoli finisce sotto il panno o oltre la sponda, in quello spigolo nasce un impulso: lungo la normale, col rimbalzo, e di traverso, quanto lo permette l’attrito. Proprio perché l’impulso è nello spigolo e non nel centro, il dado si mette a girare e rotola. Il cubo ha la stessa inerzia su ogni asse (m per lato al quadrato diviso sei), quindi i conti restano semplici. I due dadi fra loro si urtano come due palle, e l’urto li fa anche girare.
Il lancio si calcola tutto al clic, a 480 passi al secondo, e se ne tengono sessanta al secondo: posizione e quaternione di ogni dado. Poi un tween di GSAP su un solo numero scorre i fotogrammi, con la slerp fra uno e l’altro. Così il lancio sta nella stessa timeline del bicchiere e del risultato, la velocità è un timeScale, e gli urti contro la sponda (che il calcolo ha annotato col loro istante) diventano dei call che danno il colpetto al tavolo al momento giusto.
Un dado si considera fermo quando tocca il panno, è lento e la faccia più in alto punta quasi dritta in su. Negli ultimi dodici fotogrammi viene girato del minimo che serve per stare piatto su quella faccia: un quaternione che porta il suo asse più alto sull’asse z. Il numero si legge da lì: l’asse che punta in su dice la faccia. Dopo tre secondi un freno che cresce ferma comunque i dadi, anche con un panno scivoloso e i dadi di gomma.
A ogni fotogramma la normale di ogni faccia, girata col dado, si confronta con la direzione della luce: la faccia che si volta riceve un velo scuro più fitto. L’ombra è un gradiente radiale sul panno, spostato lontano dalla luce e più largo e chiaro quanto più il dado è alto. Il bicchiere è un disegno SVG piatto sopra la scena: GSAP muove il suo piede in coordinate del tavolo, due àncore invisibili dentro il tavolo dicono dove cade sullo schermo e quanto è grande lì, e GSAP lo agita e lo rovescia intorno all’angolo in basso. La bocca, ricalcolata nelle misure del tavolo, è il punto da cui partono i dadi.
| Nome | File | Di partenza | Cosa cambia |
|---|---|---|---|
THROW | script.js | 1 | Quanto forte il bicchiere lancia i dadi: con 0.5 si fermano a metà tavolo, con 1.6 sbattono contro la sponda in fondo. |
BOUNCE | script.js | 0.42 | Quanto rimbalzano sul panno: 0 cadono di peso, 0.7 sembrano di gomma. |
FELT | script.js | 0.5 | La presa del panno: bassa i dadi scivolano, alta smettono prima di rotolare. |
SPIN | script.js | 1 | Quanto girano i dadi uscendo dal bicchiere. |
TILT | script.js | 48 | Quanto dall’alto si guarda il tavolo, in gradi: 30 quasi di lato, 62 quasi dall’alto. |
SPEED | script.js | 1 | La velocità di tutto il lancio: 2 è il doppio, 0.5 la metà, un rallentatore. |
Per un bar o un negozio di giochi da tavolo, un sito di giochi, un sorteggio o un premio a caso in una promozione, la pagina «scegli tu» di un menu, un gioco da festa, l’attesa di un risultato che deve sembrare davvero lasciato al caso.
La stessa animazione con le misure adattate: il tavolo diventa più profondo che largo, sotto il titolo e sopra il pulsante, i dadi restano grandi abbastanza da leggere i puntini e il lancio va dal fondo a sinistra verso il davanti a destra. Basta un tocco sul tavolo o sul pulsante.
Niente si muove: all’apertura tavolo, testi e dadi compaiono in dissolvenza. Al clic i dadi svaniscono, il lancio si calcola lo stesso e ricompaiono già fermi dove la fisica li ha lasciati, con la somma che compare in dissolvenza.
GSAP 3.15.0, Fraunces (font variabile) 5.3.0, Instrument Sans (font variabile) 5.3.0.
Compressi con gzip, i tre file della demo pesano 15 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.