Vai al contenuto
animorio
EN
Tutti i componenti

Lo scaffale che si riempie

Caricamento, Fisica, TransizioniGSAP, Solo CSSImpegnativaPeso compresso: Demo 17 KBGSAP 28 KBGratisScarica lo zip

Il download per ascoltare offline di un’app di audiolibri, fatto come uno scaffale fra due reggilibri d’ottone: ogni audiolibro è un libro. Quello che si scarica compare di vetro, si inclina, cade e si appoggia alla fila, e la sua tela sale dal basso con i byte; scaricato, si raddrizza scivolando al suo posto con un piccolo colpo. Se la connessione cade il libro scivola giù come una scala lungo un muro; alla fine un dito corre sulle coste, una luce passa sull’oro e la libreria si accende.

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, viewport-fit=cover">
  <title>The filling shelf</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/bricolage-grotesque@5.3.0/standard.css">
  <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">
    <!-- the offline downloads of an audiobook app, as a shelf between two brass bookends: every audiobook is a book.
         The one downloading appears as a glass ghost, tips over and leans on the row, and fills with its cloth from
         the bottom as its bytes arrive; done, it stands up and slides into the row. The books are built by script.js
         from the list at the top of it -->
    <section class="shelf" aria-labelledby="shelf-title" data-shelf>
      <div class="shelf__head">
        <div class="shelf__status">
          <p class="shelf__phase"><span class="shelf__swap" data-phase>Not on this phone yet</span></p>
          <p class="shelf__note"><span class="shelf__swap" data-note>About 10 s on this Wi-Fi</span></p>
        </div>
        <p class="shelf__big" aria-hidden="true">
          <span class="shelf__swap" data-big>1.4 GB</span>
          <svg class="shelf__tick" viewBox="0 0 28 28" data-tick><path d="M6.5 14.8l5 5 10-11.4" pathLength="1"/></svg>
        </p>
      </div>
      <div class="shelf__case" role="progressbar" aria-labelledby="shelf-title" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0" aria-valuetext="Not downloaded" data-bar>
        <div class="shelf__light" aria-hidden="true" data-light></div>
        <div class="shelf__row" aria-hidden="true" data-row>
          <span class="bookend bookend--start"></span>
          <span class="bookend bookend--end" data-end></span>
        </div>
        <div class="shelf__board" aria-hidden="true"></div>
      </div>
      <div class="shelf__foot">
        <div class="shelf__list">
          <h2 class="shelf__title" id="shelf-title">For the flight</h2>
          <p class="shelf__meta" data-meta>10 audiobooks · 22 h</p>
        </div>
        <div class="shelf__buttons">
          <button class="pill pill--icon" type="button" aria-label="Cancel download" data-cancel hidden>
            <svg viewBox="0 0 24 24" aria-hidden="true"><path d="M7.5 7.5l9 9M16.5 7.5l-9 9"/></svg>
          </button>
          <button class="pill" type="button" data-action data-autoclic><span class="pill__label" data-label>Download</span></button>
        </div>
      </div>
      <p class="sr" role="status" aria-live="polite" data-live></p>
    </section>
  </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.

67 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 «Lo scaffale che si riempie» da Animorio e adattala al mio sito

Cosa fa

Su un fondo bianco, da sola al centro, una scheda verde scuro come l’interno di una libreria dipinta, larga 400 pixel: in alto Not on this phone yet e About 10 s on this Wi-Fi, e a destra, grande e stretto, 1.4 GB; in mezzo una mensola di rovere che va da un bordo all’altro della scheda, con due reggilibri d’ottone ai due capi e niente in mezzo; sotto, For the flight con 10 audiobooks · 22 h e il pulsante Download. Premuto, il pulsante diventa Pause col contorno, accanto compare la croce per annullare e il primo libro, Salt Road, compare di vetro vicino al reggilibri di sinistra: è un libro trasparente con il titolo e le fasce impressi a secco, che scende di qualche pixel come se lo si posasse, si inclina fino al punto in cui sta in bilico, esita, poi cade e si appoggia al reggilibri con un piccolo rimbalzo. Arrivati i primi byte (Connecting, poi Downloading Salt Road) la sua tela rossa sale dal basso con una riga di luce sul bordo, e con lei il titolo in oro; in alto la percentuale conta, sotto 2 of 10 books · about 6 s left, e accanto al nome della lista i megabyte scaricati, 412 MB of 1.4 GB. Quando il libro è pieno si raddrizza scivolando verso la fila, come spinto, batte contro il vicino, dondola un attimo sull’altro spigolo e si ferma; intanto dietro di lui compare di vetro il libro dopo, che cade e si appoggia a lui. Ogni libro ha il suo colore, il suo spessore (quello del suo audiolibro), la sua altezza e la sua costa: oro su tela rossa, blu, viola, verde, un’etichetta nera sul giallo, inchiostro scuro sul salvia, sul rosa e sull’avorio con le fasce rosse; i titoli lunghi vanno su due righe o si stringono sull’asse della larghezza del carattere. La connessione va a strappi e a volte si ferma un attimo, e la tela sale e si ferma con lei. Pause ferma tutto (Paused, 3 of 10 books are on this phone, Resume); la croce toglie i libri dallo scaffale, uno dopo l’altro da destra, e resta Download canceled. Una volta su due, nella demo, verso il 58% la connessione cade: il libro che si stava scaricando, appena posato, scivola col piede verso destra e la cima giù lungo il libro prima, come una scala che scivola lungo un muro, fino a restare quasi sdraiato; il suo vetro si tinge di rosso e in alto compare Couldn’t download Hollow Bells, The connection dropped, col pulsante Try again, che lo rialza e fa ripartire i byte. L’ultimo libro scende dritto nell’ultimo posto, esatto, fra la fila e il reggilibri; poi un dito corre sulle coste da sinistra (ogni libro si alza di qualche pixel e ricade), una luce passa sull’oro dei titoli, la parete dietro i libri si accende di una luce calda, la percentuale lascia il posto a una spunta che si disegna e il testo diventa Ready to listen offline, 10 of 10 books · downloaded in 9 s, 1.4 GB on this phone. Remove downloads toglie i libri e lo scaffale torna vuoto.

Come funziona

Un libro che cade

Un libro è un rettangolo rigido spesso t e alto h che gira attorno allo spigolo su cui poggia. Il suo peso gli dà un’accelerazione angolare θ'' = 3g(h·sin θ − t·cos θ) ÷ 2(t² + h²), negativa sotto l’angolo di bilico atan(t/h) (il libro torna dritto) e positiva sopra (cade). Per questo il libro viene posato mezzo grado oltre il bilico, con una spinta minima: esita, accelera e batte. Il conto si fa sul ticker di GSAP in quattro sottopassi, col fotogramma limitato a 1/30 di secondo; all’urto la velocità si capovolge e si riduce di BOUNCE.

Il contatto col libro prima

Col piede a una distanza g dalla fila, l’angolo a cui il libro si appoggia viene dal contatto: o la sua faccia tocca lo spigolo in cima al libro prima (tan θ = g ÷ H, se il libro è abbastanza alto da arrivarci), o il suo spigolo in cima tocca il fianco di quel libro (sin θ = g ÷ h). Vale il primo dei due. La stessa funzione serve quando è appoggiato, quando si raddrizza scivolando verso la fila (g va a zero e l’angolo con lui) e quando scivola via nell’errore: il piede va a destra finché il libro è a 64 gradi o tocca il reggilibri, proprio come una scala che scivola lungo un muro. Così un libro non passa mai dentro un altro.

Dove si posa, e il dondolio

Il libro che si scarica si appoggia a LEAN gradi, ma sempre almeno 7 gradi oltre il suo bilico (un libro spesso deve inclinarsi di più per non tornare dritto); se fra la fila e il reggilibri non c’è spazio per inclinarsi così, sta dritto accanto alla fila, e l’ultimo scende dritto nel suo posto. Raddrizzandosi batte contro il vicino con la velocità che aveva e dondola sull’altro spigolo: il perno cambia, la gravità lo riporta indietro, il vicino lo ferma e gli toglie un po’ di slancio a ogni colpo, e oltre 0,6 del bilico viene trattenuto.

I byte e la tela

Il download finto è una timeline di arrivi di grandezza e intervallo casuali con un paio di soste; i libri seguono i byte con un ritardo di FOLLOW secondi, ma chiudono l’ultimo pezzo a passo costante, altrimenti una rincorsa esponenziale resterebbe al 99%. La tela è un livello sopra il vetro tagliato dal basso con clip-path: inset(), il cui ritaglio si allarga di 12 pixel ai lati per lasciar passare la sua ombra. Se i libri restano indietro (ognuno ha quasi un secondo di movimento suo) si affrettano di 1,6 o 2,2 volte, e un errore si mostra solo quando il libro che non è arrivato è giù sullo scaffale.

Le coste e la luce alla fine

Le coste sono div con writing-mode vertical-rl; un titolo troppo lungo per la sua costa prima si stringe un poco (sui caratteri bastoni sull’asse wdth di Bricolage Grotesque), poi, su un libro spesso, va su due righe tagliate allo spazio più vicino al mezzo se le due metà sono equilibrate, e solo alla fine rimpicciolisce. L’oro è un gradiente con background-clip: text. Alla fine la stessa fascia di luce attraversa tutti i libri: ogni costa ha la sua copia del gradiente spostata di dove sta il libro (--bx), così si legge come una luce sola; poi la parete dietro i libri si accende con un gradiente caldo che si allarga dal mezzo.

Valori da cambiare

NomeFileDi partenzaCosa cambia
SECONDSscript.js8Quanto dura il download nella demo, in secondi (uno vero segue i suoi byte).
BOOKSscript.js[['Salt Road', 142], ['Night Ferry', 96], …]Gli audiolibri da sinistra: il titolo sulla costa e la grandezza in megabyte, che fa anche lo spessore del libro. Da 2 a 14.
FAIL_EVERYscript.js2Nella demo, un download ogni quanti perde la connessione (0 mai).
FAIL_ATscript.js0.58Fin dove arriva il download che va storto, da 0 a 1.
STALLSscript.js1Quanto spesso la connessione si ferma un attimo: 0 mai, 1 ogni tanto, 2 spesso.
LEANscript.js30Quanto si inclina sulla fila il libro che si scarica, in gradi (sempre almeno 7 oltre il punto in cui tornerebbe dritto).
GRAVITYscript.js3400Quanto forte cadono i libri, in pixel al secondo al quadrato.
BOUNCEscript.js0.32Quanto rimbalza un libro sul libro su cui cade: 0 niente, 0,6 molto.
FOLLOWscript.js0.25Quanto ci mettono i libri a raggiungere i byte, in secondi.

Provali nel Playground

Quando usarla

Per un’app di audiolibri, di ebook, di podcast o di musica che scarica una lista per ascoltarla o leggerla senza rete, per una biblioteca digitale o un’app di fumetti, e in generale per un download in coda di più elementi che hanno un nome, dove vale la pena vedere quali sono già arrivati.

Sul telefono

La scheda è larga 400 pixel e sul telefono prende la larghezza dello schermo meno 16 pixel per lato (358 a 390): i libri si fanno più sottili per riempire la mensola e i titoli si riadattano alle coste. I pulsanti sono alti 44 e si usano col tocco; la pillola che si gonfia sotto il puntatore c’è solo col mouse. Sotto i 390 pixel un messaggio d’errore molto lungo finisce coi puntini.

Con il movimento ridotto

I libri compaiono già dritti al loro posto e la tela entra con una dissolvenza man mano che arrivano i byte: niente caduta, niente dondolio, niente scivolata nell’errore (il vetro del libro si tinge di rosso). Alla fine niente dito sulle coste né fascia di luce: la luce della libreria si accende con una dissolvenza e compare la spunta. Le parole cambiano con una dissolvenza.

Trappole

  • In una timeline un fromTo() disegna subito il suo stato di partenza: le parole vecchie sparivano di colpo invece di scivolare via, perché il fromTo delle nuove (opacità 0) era già applicato. Ci vuole immediateRender: false.
  • gsap.ticker.time si ferma quando il ticker di GSAP dorme: l’anteprima, che lascia la mensola piena in vista almeno 0,8 secondi prima di svuotarla, aspettava per sempre. I tempi si prendono da performance.now().
  • gsap.killTweensOf(libro) ferma i tween ma non le chiamate dentro la timeline del libro: un libro tolto dallo scaffale tornava a cadere. Ogni libro tiene la sua timeline e la sua chiamata al libro dopo, e si fermano insieme.
  • Il clip-path che fa salire la tela taglia anche la sua ombra: il ritaglio va allargato ai lati con valori negativi, inset(… -12px -12px -12px).
  • Con LEAN molto alto e la gravità bassa il libro che si raddrizzava arrivava così veloce da cadere dall’altra parte e attraversare la mensola: il dondolio viene trattenuto a 0,6 del bilico, e nel Playground LEAN arriva a 45.
  • Una rincorsa esponenziale non arriva mai: la percentuale restava al 99% per più di un secondo e ogni libro aspettava l’ultimo per cento. Le ultime frazioni si chiudono a passo costante.
  • Ogni libro ha quasi un secondo di movimento suo: coi libri piccoli lo scaffale restava due libri indietro e l’errore nominava un libro che non era ancora comparso. I libri indietro si affrettano, e l’errore aspetta che il libro sia giù.
  • Con due soli libri lo spessore proporzionale ne faceva due scatole larghe 150 pixel: un libro non supera i 48 e il reggilibri di destra si avvicina.

Librerie

GSAP 3.15.0, Bricolage Grotesque (font variabile) 5.3.0, Fraunces (font variabile) 5.3.0.

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

Collaudo

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

Tutti i componenti