Vai al contenuto
animorio
EN
Torna alla libreria

Il titolo di tessere di legno

Testo, FisicaGSAPImpegnativaPeso compresso: Demo 15 KBGSAP 28 KBGratisScarica lo zip

Un sacchetto di stoffa cade sul tavolo verde, si apre e si rovescia: tessere di legno con le lettere incise rotolano, rimbalzano, si girano a faccia in su e si incastrano su un leggio formando una frase, che saluta con un’onda. Un clic le rimescola: quelle che servono saltano e girano in aria, le altre tornano nel sacchetto.

Il codice

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 wooden tile title</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/fraunces@5.3.0/index.css">
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <main class="stage" data-stage data-autoclic role="button" tabindex="0" aria-label="Shuffle the tiles">
    <!-- the phrase on the rack, for screen readers: the script keeps it in step with the tiles -->
    <h1 class="reader" data-reader>The Oak Room</h1>
    <!-- the table seen from above at an angle: the bag, the rack and the tiles live in a tilted 3D plane; every tile is a box made of divs -->
    <div class="world" data-world>
      <div class="bag" data-bag>
        <div class="bag__tip" data-bag-tip>
          <svg class="bag__svg" viewBox="0 0 200 220" aria-hidden="true">
            <defs>
              <radialGradient id="bag-cloth" cx="0.36" cy="0.42" r="0.75">
                <stop offset="0" stop-color="var(--bag-light)"/>
                <stop offset="0.55" stop-color="var(--bag)"/>
                <stop offset="1" stop-color="var(--bag-dark)"/>
              </radialGradient>
              <linearGradient id="bag-ruffle" x1="0" y1="0" x2="1" y2="0">
                <stop offset="0" stop-color="var(--bag-dark)"/>
                <stop offset="0.4" stop-color="var(--bag-light)"/>
                <stop offset="1" stop-color="var(--bag-dark)"/>
              </linearGradient>
              <pattern id="bag-weave" width="4" height="4" patternUnits="userSpaceOnUse">
                <path d="M0 1h4M1 0v4" stroke="var(--bag-dark)" stroke-width="0.6" opacity="0.35"/>
              </pattern>
            </defs>
            <path class="bag__body" data-bag-body fill="url(#bag-cloth)"/>
            <path class="bag__weave" data-bag-weave fill="url(#bag-weave)"/>
            <g class="bag__folds" data-bag-folds fill="none" stroke="var(--bag-dark)" stroke-linecap="round"></g>
            <g class="bag__patch" transform="rotate(-5 100 156)">
              <rect x="70" y="140" width="60" height="32" rx="5" fill="var(--patch)"/>
              <rect x="73.5" y="143.5" width="53" height="25" rx="3" fill="none" stroke="var(--bag)" stroke-width="1" stroke-dasharray="3 2.4"/>
              <text x="100" y="161.5" text-anchor="middle" font-size="12.5" font-weight="700" letter-spacing="1.4" fill="var(--bag-dark)">TILES</text>
            </g>
            <path class="bag__ruffle" data-bag-ruffle fill="url(#bag-ruffle)"/>
            <ellipse class="bag__mouth" data-bag-mouth fill="var(--bag-inside)"/>
            <path class="bag__lip" data-bag-lip fill="none" stroke="var(--bag-light)" stroke-width="2.6" stroke-linecap="round"/>
            <rect class="bag__band" data-bag-band fill="var(--string)" rx="4.5"/>
            <path class="bag__cords" data-bag-cords fill="none" stroke="var(--string)" stroke-width="3.2" stroke-linecap="round" stroke-linejoin="round"/>
            <g data-bag-knots fill="var(--string)"><circle r="3.4"/><circle r="3.4"/></g>
          </svg>
        </div>
      </div>
    </div>
    <div class="lamp" aria-hidden="true"></div>
    <p class="hint" data-hint>Click or tap to shuffle the tiles</p>
  </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

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.

22 valori da cambiare

Oppure chiedila a Claude Code

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 titolo di tessere di legno» da Animorio e adattala al mio sito

Cosa fa

Un tavolo da gioco coperto di panno verde, visto dall’alto e un po’ di sbieco, con una lampada che lo illumina al centro. In fondo, a sinistra, cade dall’alto un sacchetto di stoffa rossa con il cordino e un’etichetta cucita: tocca il panno e si schiaccia rimbalzando. Il cordino si allenta, il collo si allarga e si vede il buio dentro; il sacchetto si piega un attimo all’indietro per prendere lo slancio e si rovescia sul fianco. Ne escono una dopo l’altra le tessere: sono scatolette di legno chiaro con la grana, lo spessore e i bordi più scuri, e una lettera incisa sulla faccia. Volano, toccano il panno, rimbalzano tre volte sempre più basse e intanto girano su se stesse finché si fermano storte, alcune a faccia in giù; sotto ognuna l’ombra si stringe e si scurisce quando scende. Il sacchetto, ormai sgonfio, si rimette in piedi dondolando. Le tessere girate al contrario fanno un salto e si capovolgono, le altre si raddrizzano con un piccolo scatto; poi, una dopo l’altra, scivolano verso il leggio di legno in primo piano, saltano oltre la sponda e si incastrano in piedi nel loro posto, con il leggio che sobbalza a ogni arrivo. Quando la frase è completa, «The Oak Room», le tessere fanno un saltello in fila, come un’onda. Un clic (o un tocco) le rimescola: il sacchetto fa un balzo e si spalanca, le tessere si accucciano e saltano. Quelle che servono anche nella frase dopo restano, ma volano in un posto nuovo girando su se stesse e atterrano con un rimbalzo; quelle che non servono volano dentro il sacchetto, che le inghiotte; quelle che mancano saltano fuori dal sacchetto e raggiungono il loro posto. Il leggio si allunga o si accorcia con la frase e alla fine l’onda saluta di nuovo. Sul computer, passando sopra una tessera, questa si sporge verso di te. Su uno schermo stretto la frase va a capo su più leggii, uno dietro l’altro.

Come funziona

Un mondo inclinato

Il palco ha una prospettiva (perspective) e dentro c’è un solo div, il mondo, inclinato con rotateX(50deg) e transform-style: preserve-3d: x va a destra, y verso di noi, z sale dal panno. Tutto quello che sta sul tavolo vive lì dentro e GSAP lo muove con x, y, z e le rotazioni. Lo script rifà la stessa matematica del browser (la rotazione e la divisione per la prospettiva) in due funzioni: project porta un punto del mondo sullo schermo, onFelt fa il contrario per il panno. Così il leggio si mette all’83% dell’altezza dello schermo, il sacchetto al 35% e le tessere atterrano solo nella parte visibile fra i due.

La tessera è una scatola

Ogni tessera ha tre livelli: il primo la mette al suo posto e la alza in piedi (rotationX di meno 50 gradi, così la faccia guarda proprio l’occhio), il secondo serve all’hover, il terzo fa le capriole. Dentro ci sono sei facce con backface-visibility: hidden, misurate con due variabili CSS, --s per il lato e --t per lo spessore. La grana è una canvas disegnata una volta dallo script (venature ondulate, fasce e un nodo) e messa come immagine di sfondo, spostata a caso per ogni tessera; il colore viene da WOOD. La lettera è incisa con due text-shadow: luce sul bordo basso del taglio, ombra su quello alto.

Rotolare e rimbalzare

Ogni tessera esce dalla bocca del sacchetto, che lo script calcola ruotando il punto del disegno intorno all’angolo su cui il sacchetto si rovescia. Il volo sono tre tween insieme: x e y con power3.out (corre e frena), z con otto keyframes (il primo arco, poi tre rimbalzi sempre più bassi, con power2.in in discesa e power2.out in salita), e le capriole su rotationX e rotationY che finiscono su un giro intero, o su mezzo giro per quelle che restano a faccia in giù. Le ombre sono macchie sul panno che un ticker sposta a ogni fotogramma sotto la tessera: più è alta, più l’ombra si allarga, si sposta e sbiadisce.

Il leggio e l’incastro

I posti nel leggio si contano in lati di tessera: lo spazio fra le parole, il margine ai lati, e se la frase non ci sta va a capo su un altro leggio dietro. Il lato è lo stesso per tutte le frasi, quello che fa stare la più lunga. Per arrivare, la tessera scivola sul panno fino dietro al suo posto, poi con due keyframes salta oltre la sponda alzandosi in piedi e cade nel posto con back.out, che dà lo scatto dell’incastro; il leggio sobbalza con un fromTo su z. Il leggio è fatto di pezzi corti affiancati, tutti paralleli alle tessere in piedi: il browser non deve ordinare piani che si incrociano.

Il rimescolio

Al clic ogni posto della frase nuova cerca, fra le tessere sul leggio, una con la stessa lettera, la più vicina. Le tessere trovate volano al posto nuovo con un arco su z e un giro intero su rotationY; quelle rimaste senza posto volano nella bocca del sacchetto, rimpiccioliscono e spariscono, e il sacchetto si schiaccia come se le inghiottisse; per i posti senza tessera ne escono di nuove dal sacchetto (le vecchie si riusano). Il leggio cambia lunghezza con un tween. Un clic che arriva mentre le tessere sono in aria viene tenuto da parte e parte appena finiscono; SPEED è il timeScale di ogni timeline.

Valori da cambiare

NomeFileDi partenzaCosa cambia
PHRASESscript.js['THE OAK ROOM', 'TEA AND TILES', 'GAME NIGHT', 'OPEN LATE']Le frasi sul leggio, una per clic: dopo l’ultima si ricomincia dalla prima. Lettere, numeri e i segni & ! ? ' . , -, al massimo 28 caratteri; se non ci stanno in una riga vanno a capo su più leggii.
TOSSscript.js1La forza con cui il sacchetto butta le tessere: quanto in alto rimbalzano, quante capriole fanno e quanto in alto saltano per girarsi.
SHUFFLEscript.js1Il rimescolio: quanto in alto saltano le tessere e quanti giri fanno in aria (2 = due giri e salti più alti).
WOODscript.js'#e2bd86'Il colore del legno delle tessere: lo script ne ricava i bordi più scuri e il colore dell’incisione.
SPEEDscript.js1La velocità di tutta l’animazione: 2 è il doppio, 0.5 la metà.

Provali nel Playground

Quando usarla

Per il titolo di un sito che parla di giochi, parole o tempo libero: un caffè con i giochi da tavolo, un club, un locale per le serate a quiz, una scuola di lingue, un’app di parole, un festival; per una pagina che deve cambiare frase al clic, come un saluto, una promessa o un anagramma.

Sul telefono

La stessa animazione con le misure adattate: le tessere sono più piccole e la frase va a capo su due o tre leggii, uno dietro l’altro; il sacchetto e le tessere che rotolano stanno nello spazio sopra. Un tocco le rimescola.

Con il movimento ridotto

Niente si muove: il sacchetto aperto e le tessere già sul leggio compaiono in dissolvenza. Al clic le tessere svaniscono e quelle della frase dopo compaiono al loro posto.

Trappole

  • Il leggio era una scatola lunga fatta di facce in 3D: in Chrome ne veniva disegnata solo una metà, e le facce si ordinavano male fra loro. Ora è fatto di pezzi corti affiancati, tutti paralleli alle tessere in piedi: niente piani che si incrociano, niente piani troppo lunghi.
  • Le tessere a terra sono tutte alla stessa altezza: dove si sovrappongono le facce sfarfallano. Ognuna ha un piccolo scarto in z (qualche decimo di pixel) e i punti d’arrivo sono lontani almeno un lato e mezzo; le lettere si assegnano da sinistra a destra, così le strade verso il leggio si incrociano poco.
  • Le facce misurate con le variabili --s e --t restano a zero se la tessera nasce dopo il calcolo delle misure: ogni tessera nuova riceve le variabili appena viene presa dal mucchio.
  • Le tessere tornate nel sacchetto lasciavano la loro ombra sul panno: il ticker nasconde l’ombra di ogni tessera che non è in gioco.
  • Il clic del pilota automatico arriva ogni tre secondi circa, anche mentre le tessere sono in aria: invece di accavallare due rimescolii, il clic viene tenuto da parte e parte appena l’onda finisce.
  • Una rotazione di 360 gradi lasciata così fa sì che il giro dopo, che va a 360, non giri affatto: alla fine di ogni volo rotationY torna a 0 con un set.

Librerie

GSAP 3.15.0, Fraunces (font variabile) 5.3.0.

Compressi con gzip, i tre file della demo pesano 15 KB; le librerie: GSAP 28 KB.

Collaudo

Provata il 10 ottobre 2026

  • Computer: Fatto
  • Telefono: Fatto
  • Movimento ridotto: Fatto
  • Safari su iPhone: Da fare

Licenza d’uso

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.

Tutte le animazioni