Vai al contenuto
animorio
EN
Torna alla libreria

La galleria a scatole cinesi

Immagini, TransizioniGSAP, CanvasImpegnativaPeso compresso: Demo 8,9 KBGSAP + CustomEase 31 KBGratisScarica lo zip

Nello stile minimal: cinque immagini astratte una dentro l’altra. Ogni immagine ha al centro una cornice sottile con dentro la successiva; al clic la camera fa un respiro indietro, poi entra nella cornice con uno zoom esponenziale misurato, va oltre di tre pixel e si assesta, e l’immagine dentro diventa la pagina, mentre la didascalia rotola lettera per lettera. L’ultima contiene di nuovo la prima, quindi non finisce mai.

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>Inward</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/archivo@5.3.0/wdth.css">
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <!-- five pictures, one inside the other: each one holds the next in a thin frame in its middle -->
  <main class="room" data-room data-autoclic tabindex="0" role="region" aria-roledescription="gallery" aria-label="Inward, a gallery of pictures one inside the other. Click, tap or press the right arrow to step into the frame; the left arrow steps back out.">
    <canvas class="stage" data-stage aria-hidden="true"></canvas>

    <header class="top">
      <p class="mark" data-mark aria-hidden="true">Inward</p>
      <p class="sub" data-sub>Five rooms, one inside the other</p>
    </header>

    <div class="caption" aria-hidden="true">
      <p class="caption__title"><span class="slot" data-title></span></p>
      <p class="caption__note"><span class="slot" data-note></span></p>
    </div>

    <p class="hint" data-hint aria-hidden="true">Click to step inside</p>
    <p class="sr" data-live aria-live="polite"></p>
  </main>

  <script src="https://cdn.jsdelivr.net/npm/gsap@3.15.0/dist/gsap.min.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/gsap@3.15.0/dist/CustomEase.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.

23 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 «La galleria a scatole cinesi» da Animorio e adattala al mio sito

Cosa fa

Una pagina color carta con in alto a sinistra il nome di una galleria inventata, Inward, e a destra una riga piccola. Al centro c’è un grande disco color pietra che tramonta dietro una riga sottile d’orizzonte, con un trattino vermiglio sull’acqua: è la prima immagine, Low sun. Sul disco una riga nera sottile si disegna tutto intorno a un rettangolo, poi dentro si apre da una linea orizzontale, con una molla, una finestra: dentro c’è la seconda immagine, una porta ad arco color carta su un muro nero, che ha a sua volta la sua cornice con dentro la terza, e così via, sempre più piccole. Sotto la cornice, piccolo come l’etichetta di un museo, c’è il titolo dell’immagine che contiene; in basso a sinistra salgono il titolo della pagina e una nota, lettera per lettera. Dopo un paio di secondi, o al clic, la camera fa un respiro indietro (ai bordi si vede per un attimo l’immagine che contiene questa) e poi si tuffa nella cornice: lo zoom cresce dello stesso fattore a ogni istante, quindi la velocità sembra costante, frenato solo all’inizio e alla fine; la riga della cornice esce dallo schermo, l’etichetta cresce e svanisce prima di arrivare in basso, la camera va oltre di tre pixel e torna indietro con un piccolo elastico. Ora l’arco è la pagina, le scritte sono diventate color carta per leggersi sul nero e la didascalia è rotolata al titolo nuovo. Le cinque immagini sono il sole basso, la porta ad arco con la soglia vermiglia, righe sottili che si allargano allontanandosi dalla finestra con una sola riga vermiglia, una griglia disegnata sulla misura della cornice con un quadrato vermiglio e un anello sottile su fondo nero con un sole vermiglio in eclissi; l’ultima contiene di nuovo la prima. Col mouse sopra la cornice la camera si avvicina un poco, come per guardare meglio, e il prossimo tuffo aspetta. Le frecce della tastiera entrano ed escono, sul telefono si tocca per entrare e si scorre a destra per tornare fuori.

Come funziona

Una sola mappa, un solo numero

Ogni immagine è disegnata nella stessa scatola grande quanto la pagina, e la sua finestra è la stessa scatola rimpicciolita di SCALE e spostata nel punto (x0, y0): un punto dell’immagine dopo finisce in (x0, y0) più SCALE per il punto. Questa mappa ha un solo punto che non si muove, F = (x0, y0) / (1 − SCALE). Ingrandendo di 1/SCALE intorno a F, la finestra cade esattamente sulla pagina e tutte le immagini più dentro la seguono. Così la camera è un numero solo, d: 0 è la prima immagine come pagina, 1 la seconda, 0,5 a metà strada; l’immagine k livelli più dentro si disegna ingrandita di SCALE alla (k − d) intorno a F.

Il disegno, dal più grande al più piccolo

A ogni fotogramma il ticker di GSAP disegna su una canvas la pagina, poi l’immagine nella sua finestra, poi quella dentro, finché la successiva sarebbe più piccola di due pixel: ognuna copre la finestra della precedente. Il livello di partenza è la parte intera di d, quindi d può crescere all’infinito e il giro torna da solo alla prima immagine (il resto della divisione per il numero di immagini). Con d appena sotto un intero (il respiro indietro) si disegna anche l’immagine che contiene la pagina, che si vede ai bordi.

Lo zoom esponenziale

Il tween muove d, non la scala: la scala è SCALE alla −d, quindi a passi uguali di d corrisponde sempre lo stesso fattore di ingrandimento, e l’occhio sente una velocità costante. La curva ZOOM_EASE (una CustomEase) frena solo l’inizio e la fine. Prima c’è un respiro indietro di 0,014 in un quarto di secondo; dopo, d va oltre il bersaglio di quel tanto che al bordo della pagina fa OVERSHOOT pixel (il logaritmo di 1 + OVERSHOOT / metà larghezza, diviso il logaritmo di 1/SCALE) e torna con elastic.out.

Righe sottili a ogni profondità

Le forme si disegnano nella scala del loro livello, ma le righe no: lo spessore sullo schermo è la scala alla 0,4, fra 0,45 e 1,4 pixel, quindi una riga resta un capello sia sulla pagina sia tre livelli più dentro, e cambia con continuità durante lo zoom (nessun salto quando l’immagine diventa la pagina). La cornice si disegna in pixel dello schermo, sul mezzo pixel quando la pagina è ferma, così è nitida. L’etichetta sotto la cornice si scrive nella scala del suo livello e sparisce sotto i due pixel di corpo; durante il tuffo svanisce prima di arrivare alla didascalia.

L’apertura, la didascalia e i colori

All’apertura la riga della cornice si disegna con setLineDash, poi la prima finestra si apre da una linea con una molla vera: tutto quello che c’è più dentro resta tagliato in quel rettangolo. La didascalia è in fessure con overflow nascosto: le lettere vecchie escono in alto quando la camera è dentro la cornice, quelle nuove salgono quando atterra, con l’asse wdth del carattere da 72 a 100 su un elastico. Quando il fondo nuovo copre quasi tutta la pagina, GSAP porta le variabili --fg e --muted al colore che si legge su quel fondo.

Valori da cambiare

NomeFileDi partenzaCosa cambia
PICTURESscript.js[{ title: 'Low sun', note: 'Stone and vermilion on paper' }, …]Le immagini, in ordine: il titolo (anche l’etichetta sotto la cornice che la contiene) e la nota piccola sotto il titolo. I disegni sono cinque e si ripetono se le voci sono di più.
SCALEscript.js0.3Quanto è grande la cornice nella pagina: 0,3 vuol dire tre decimi. Più è piccola, più lungo è il tuffo e più immagini si vedono una dentro l’altra.
ZOOMscript.js2.1Quanti secondi impiega la camera ad attraversare la cornice.
ZOOM_EASEscript.jsCustomEase.create('inward', '0.62, 0, 0.24, 1')La curva del tuffo: frena l’inizio e la fine di uno zoom che per il resto va a velocità costante.
OVERSHOOTscript.js3Di quanti pixel la camera va oltre prima di assestarsi (0 = arriva liscia).
HOLDscript.js2.4Quanti secondi resta ogni immagine prima del tuffo successivo.
MATscript.js10Lo spazio fra la finestra e la sua riga sottile, in pixel.
AUTOPLAYscript.jstrueSe la camera entra da sola. Con false entra solo col clic, col dito o con le frecce.

Provali nel Playground

Quando usarla

Per una galleria o un portfolio che deve sembrare un percorso e non una griglia: la pagina di una mostra, il sito di un artista o di un fotografo, la presentazione di una serie, il passaggio fra i capitoli di un progetto. Funziona con immagini che hanno un centro libero, o con illustrazioni pensate apposta per contenere la successiva.

Sul telefono

La stessa animazione con le misure adattate: la pagina è verticale, quindi anche le cornici lo sono, un po’ più grandi e un po’ più in alto per lasciare posto alla didascalia. Un tocco entra, lo scorrere del dito a destra torna fuori, a sinistra entra.

Con il movimento ridotto

Niente zoom: tutto compare in dissolvenza, e a ogni passo la pagina e la didascalia svaniscono e ricompaiono con l’immagine dopo, senza respiro, elastico né lettere che rotolano.

Trappole

  • Lo zoom va fatto intorno al punto fisso della mappa, F = (x0, y0) / (1 − SCALE), non intorno al centro della cornice: la cornice non sta al centro (la pagina lascia posto alla didascalia) e intorno al suo centro i livelli più dentro scivolerebbero di lato e il giro non tornerebbe uguale. Intorno a F ogni livello è lo stesso disegno, solo più grande, e muovendo d (l’esponente) e non la scala lo zoom si sente esponenziale.
  • Le righe delle onde e il quadrato della griglia, disegnati su tutta la pagina, passavano sotto il nome in alto e sotto la didascalia (sul telefono la nota era tagliata da una riga) e il quadrato vermiglio toccava l’etichetta: le righe si fermano fra il 12% e l’84% dell’altezza e il quadrato sta a destra della cornice, lontano dall’etichetta.
  • Il respiro indietro all’inizio del tuffo mostra ai bordi l’immagine che contiene la pagina: con 0,022 erano bande scure di venti pixel che sembravano un errore; con 0,014 sono un filo che si legge come un respiro.
  • L’etichetta sotto la cornice, ingrandendo, arrivava in basso a sinistra proprio quando la didascalia stava cambiando, e per un attimo c’erano due titoli uno sull’altro: l’etichetta svanisce quando supera 1,35 volte la sua misura.
  • Il colore del testo sta in una variabile sul contenitore, ma body lo aveva già calcolato e lo passava ai figli già risolto: le scritte restavano nere sul fondo nero. Il colore va dichiarato sul contenitore stesso (color: var(--fg)).
  • Il primo fotogramma, disegnato prima della timeline d’apertura, mostrava già tutto e poi spariva: gli stati di partenza si mettono con gsap.set prima del primo disegno.

Librerie

GSAP 3.15.0, Archivo (font variabile) 5.3.0.

Compressi con gzip, i tre file della demo pesano 8,9 KB; le librerie: GSAP + CustomEase 31 KB.

Collaudo

Provata il 15 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