Vai al contenuto
animorio
EN
Torna alla libreria

L’aeroplanino di carta

Scroll, SVGGSAPImpegnativaPeso compresso: Demo 17 KBGSAP + ScrollTrigger 45 KBLenis 5,3 KBGratisScarica lo zip

Scorri dentro l’anteprima

La pagina di un servizio postale inventato: in cima un foglio di carta per posta aerea si piega da solo in 3D in un aeroplanino. Scorrendo l’aeroplanino vola giù per la pagina su un percorso curvo, si piega nelle curve, sfiora i blocchi di testo che si scansano con un elastico, fa un giro della morte e lascia una scia tratteggiata rossa e blu; in fondo plana dentro una cassetta delle lettere che si chiude e alza la bandierina.

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>L'aeroplanino di carta</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/mona-sans@5.3.0/standard.css">
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <header class="barra">
    <a class="marchio" href="#" aria-label="Paperwing Post, home">
      <svg class="marchio__segno" viewBox="0 0 40 40" aria-hidden="true">
        <rect class="marchio__bordo" x="3" y="3" width="34" height="34" rx="3" />
        <path class="marchio__ala" d="M9 21L31 11L22 30L19 23Z" />
        <path class="marchio__piega" d="M19 23L31 11" />
      </svg>
      <span>Paperwing Post</span>
    </a>
    <nav class="voci" aria-label="Main">
      <a class="voce" href="#rotta">Rates</a>
      <a class="voce" href="#giro">Express</a>
      <a class="voce" href="#arrivo">Track</a>
    </nav>
  </header>

  <main>
    <!-- the opening: the sheet of paper folds itself into a plane -->
    <section class="apertura" data-apertura>
      <div class="apertura__testo">
        <p class="occhiello" data-entra>Airmail without the airport</p>
        <h1 class="titolo">
          <span class="riga"><span data-riga>Letters that</span></span>
          <span class="riga"><span data-riga><em>fly themselves.</em></span></span>
        </h1>
        <p class="sotto" data-entra>Write it, fold it, let it go. Paperwing Post handles the wind, the weather and the last ten metres to the door.</p>
        <div class="azioni" data-entra>
          <a class="pillola" href="#arrivo"><span class="pillola__fondo"></span><span class="pillola__testo">Send a letter</span></a>
          <p class="cenno" data-cenno><span>Scroll to launch</span>
            <svg viewBox="0 0 24 32" aria-hidden="true"><path d="M12 4V27M5 20L12 27L19 20" /></svg>
          </p>
        </div>
      </div>
      <div class="apertura__foglio" data-posto-foglio aria-hidden="true"></div>
    </section>

    <!-- the route: the plane brushes past these blocks and they step aside -->
    <section class="rotta" id="rotta" data-rotta>
      <article class="blocco blocco--sx" data-blocco>
        <div class="blocco__corpo" data-corpo>
          <svg class="timbro" viewBox="0 0 80 80" aria-hidden="true" data-timbro>
            <circle cx="40" cy="40" r="30" /><circle cx="40" cy="40" r="23" />
            <text x="40" y="44">FOLDED</text>
          </svg>
          <h2 data-entra-blocco>Folded by hand</h2>
          <p data-entra-blocco>Every letter leaves the counter as a paper plane: two creases, a sharp nose and a last look against the light.</p>
        </div>
      </article>
      <article class="blocco blocco--dx" data-blocco>
        <div class="blocco__corpo" data-corpo>
          <svg class="timbro" viewBox="0 0 80 80" aria-hidden="true" data-timbro>
            <circle cx="40" cy="40" r="30" /><circle cx="40" cy="40" r="23" />
            <text x="40" y="44">ROUTED</text>
          </svg>
          <h2 data-entra-blocco>Routed by the wind</h2>
          <p data-entra-blocco>Our planes read the breeze, not the map. Expect a few curves on the way: they still arrive before the bus.</p>
        </div>
      </article>
      <article class="blocco blocco--sx" data-blocco>
        <div class="blocco__corpo" data-corpo>
          <svg class="timbro" viewBox="0 0 80 80" aria-hidden="true" data-timbro>
            <circle cx="40" cy="40" r="30" /><circle cx="40" cy="40" r="23" />
            <text x="40" y="44">WAXED</text>
          </svg>
          <h2 data-entra-blocco>Weatherproof wings</h2>
          <p data-entra-blocco>Waxed paper, a rounded nose and a tail that forgives. Rain slows us down, but only a little.</p>
        </div>
      </article>
      <article class="blocco blocco--dx" data-blocco>
        <div class="blocco__corpo" data-corpo>
          <svg class="timbro" viewBox="0 0 80 80" aria-hidden="true" data-timbro>
            <circle cx="40" cy="40" r="30" /><circle cx="40" cy="40" r="23" />
            <text x="40" y="44">TRACKED</text>
          </svg>
          <h2 data-entra-blocco>Tracked to the door</h2>
          <p data-entra-blocco>Look up. If it is folded, striped and flying low over your street, it is probably yours.</p>
        </div>
      </article>
    </section>

    <!-- the express service: the plane loops the loop here -->
    <section class="giro" id="giro" data-giro>
      <div class="giro__testo" data-blocco>
        <div class="blocco__corpo" data-corpo>
          <p class="occhiello" data-entra-blocco>Express</p>
          <h2 data-entra-blocco>One loop the loop, <em>on the house.</em></h2>
          <p data-entra-blocco>Express letters take the scenic route for a second. Nobody has ever asked for a refund.</p>
        </div>
      </div>
      <div class="giro__spazio" data-giro-spazio aria-hidden="true"></div>
    </section>

    <!-- the landing: a glide into the mailbox, the door shuts and the flag goes up -->
    <section class="arrivo" id="arrivo" data-arrivo>
      <div class="arrivo__testo" data-blocco>
        <div class="blocco__corpo" data-corpo>
          <p class="occhiello" data-entra-blocco>Last ten metres</p>
          <h2 data-entra-blocco>Straight into <em>the box.</em></h2>
          <p data-entra-blocco>No knocking, no missed deliveries. The plane glides in, the door shuts and the flag goes up.</p>
          <svg class="bollo" data-bollo viewBox="0 0 150 80" aria-hidden="true">
            <rect x="4" y="8" width="142" height="64" rx="8" />
            <rect x="11" y="15" width="128" height="50" rx="5" />
            <text x="75" y="48">DELIVERED</text>
          </svg>
        </div>
      </div>
      <div class="arrivo__cassetta" data-posto-cassetta aria-hidden="true"></div>
    </section>

    <footer class="piede">
      <p><strong>Paperwing Post</strong> Letters by air, folded by hand.</p>
    </footer>
  </main>

  <!-- the sky over the whole page: the trail, the plane and the mailbox are drawn here by the script -->
  <svg class="cielo" data-cielo aria-hidden="true">
    <defs>
      <pattern id="ap-righe" width="22" height="22" patternUnits="userSpaceOnUse" patternTransform="rotate(45)">
        <rect width="22" height="22" class="righe__carta" />
        <rect width="6" height="22" class="righe__rosso" />
        <rect x="11" width="6" height="22" class="righe__blu" />
      </pattern>
      <!-- the letter printed on the front of the sheet, in sheet units: 200 wide, 300 tall -->
      <g id="ap-lettera">
        <path class="lettera__bordo" fill-rule="evenodd" d="M-100 0H100V300H-100ZM-91 9V291H91V9Z" />
        <rect class="lettera__etichetta" x="-80" y="24" width="62" height="20" rx="2" />
        <text class="lettera__via" x="-49" y="38">BY AIR MAIL</text>
        <g class="lettera__francobollo">
          <rect x="44" y="20" width="38" height="46" />
          <rect class="francobollo__dentro" x="49" y="25" width="28" height="36" />
          <path class="francobollo__ala" d="M53 49L73 39L66 56L63 50Z" />
        </g>
        <text class="lettera__saluto" data-saluto x="-76" y="132">Dear Ada,</text>
        <path class="lettera__righe" d="M-76 156c22-4 44 3 66-1s40 2 62-1M-76 176c26-3 50 3 76 0s34 2 52-1M-76 196c20-3 40 2 60 0s46 3 70-1M-76 216c30-3 58 2 86-1M-76 236c22-2 46 3 70-1s30 2 40 0" />
        <text class="lettera__firma" x="70" y="272">June</text>
      </g>
      <!-- the back of the sheet: only the striped border -->
      <g id="ap-retro"><path class="lettera__bordo" fill-rule="evenodd" d="M-100 0H100V300H-100ZM-91 9V291H91V9Z" /></g>
      <clipPath id="ap-dentro" data-clip-dentro><rect data-clip-fuori x="0" y="0" width="0" height="0" /><path data-clip-bocca d="" /></clipPath>
      <mask id="ap-maschera" maskUnits="userSpaceOnUse" x="0" y="0" width="100" height="100" data-maschera>
        <path data-scia-maschera class="scia__maschera" d="" />
      </mask>
    </defs>
    <g mask="url(#ap-maschera)" data-scia>
      <path class="scia scia--rosso" data-scia-rosso d="" />
      <path class="scia scia--blu" data-scia-blu d="" />
    </g>
    <g data-cassetta-dietro></g>
    <g data-aereo-fuori><g data-aereo></g></g>
    <g data-cassetta-davanti></g>
  </svg>

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

52 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 «L’aeroplanino di carta» da Animorio e adattala al mio sito

Cosa fa

La pagina è quella di «Paperwing Post», un servizio postale inventato che consegna le lettere in volo. In cima, accanto al titolo «Letters that fly themselves.», compare un foglio da posta aerea con il bordo a righe rosse e blu, l’etichetta «By air mail», un francobollo e una lettera scritta a mano. Il foglio si piega da solo: i due angoli in alto scendono verso il centro, poi i nuovi bordi si piegano ancora verso il centro, il foglio si chiude a metà girandosi di lato e le ali si aprono con un piccolo rimbalzo; l’aeroplanino fa un saltello e resta sospeso, ondeggiando piano. Ogni piega è vera 3D: le facce girano intorno alle loro pieghe e si scuriscono o si schiariscono secondo come prendono la luce, e dietro il foglio è bianco con le stesse righe. Scorrendo, l’aeroplanino decolla e scende per la pagina su un percorso curvo, restando più o meno alla stessa altezza dello schermo: punta sempre nella direzione in cui va, si inclina nelle curve e quando torna indietro rotola su sé stesso per restare dritto. Passa rasente a quattro blocchi di testo, che si scansano con un elastico e si inclinano un poco, mentre i loro timbri entrano girando. Nella sezione «Express» fa un giro della morte completo, a testa in giù in cima al giro. Dietro di sé lascia una scia tratteggiata, un trattino rosso e uno blu come il bordo della busta, che finisce sempre sotto la coda. In fondo plana verso una cassetta delle lettere con lo sportello aperto, alza un poco il muso, rimpicciolisce ed entra nella bocca buia; lo sportello si chiude con un elastico, la cassetta sobbalza, partono tre segni di colpo, la bandierina rossa si alza e accanto cade il timbro «Delivered». Scorrendo indietro tutto si riavvolge e lo sportello si riapre. Il puntatore su un blocco fa fare un giro al suo timbro, sulla cassetta fa sventolare la bandierina; i link in alto fanno un’onda lettera per lettera e il pulsante si gonfia con un rimbalzo.

Come funziona

Il foglio tagliato in facce

Il foglio è largo 200 unità e alto 300, con il muso in cima. Lo script piega sulla carta metà foglio: gli angoli verso il centro, i nuovi bordi verso il centro, e a ogni piega taglia i pezzi con la retta della piega e ribalta quelli che si spostano, ricordando la strada per tornare al foglio piatto e l’elenco delle pieghe che li muovono. Poi la piega dell’ala taglia tutto un’ultima volta. Escono sedici facce (otto per lato), ognuna disegnata nelle coordinate del foglio piatto.

Le pieghe come rotazioni in 3D

Ogni piega è una rotazione intorno a una retta del foglio piatto (la formula di Rodrigues): angoli, secondi angoli, metà e ali. La posizione di una faccia è il prodotto delle rotazioni della sua catena, dalla più esterna alla più interna. L’aeroplanino è poi girato verso lo schermo: dal foglio dritto di fronte all’orientamento di volo con un’interpolazione sferica (quaternioni), e in volo con la direzione, il rollio e un poco di imbardata.

Facce SVG con la lettera stampata

Vista di lato una faccia piana resta un parallelogramma, quindi basta un transform matrix(a b c d e f) su un gruppo SVG con il poligono nelle coordinate del foglio. Dentro c’è la lettera (un use ritagliato dal clipPath della faccia) se si vede il davanti, solo il bordo a righe se si vede il dietro, e un poligono scuro la cui opacità dipende da come la faccia prende la luce. L’ordine di disegno: prima i pannelli lontani, poi su ogni pannello la pila di carta dal lato nascosto a quello visto.

Il percorso e lo scroll

Il percorso è una curva morbida (Catmull-Rom trasformata in Bézier) che passa accanto a ogni blocco, misurato dalla pagina, poi un giro della morte e la planata nella cassetta. Lo script la campiona ogni 3 pixel e per ogni punto calcola lo scroll che lo porta al 60% dello schermo; nel giro lo scroll avanza in modo uniforme, così sullo schermo il giro è rotondo. Un solo tween con ScrollTrigger e scrub porta il valore dello scroll, e una ricerca binaria trova il punto.

Scia, blocchi e cassetta

La scia sono due tracciati tratteggiati (rosso e blu sfasati) visti attraverso una maschera con un solo trattino lungo quanto tutto il percorso: lo stroke-dashoffset la scopre fino alla coda. I blocchi misurano a ogni fotogramma la distanza dall’aeroplanino e si spostano con gsap.quickTo ed elastic.out. All’arrivo una timeline chiude lo sportello (scaleY da -0,52 a 1 con elastic.out), fa sobbalzare la cassetta, alza la bandierina con back.out e fa cadere il timbro; scorrendo indietro torna al contrario.

Valori da cambiare

NomeFileDi partenzaCosa cambia
FOLD_SPEEDscript.js1Quanto in fretta il foglio si piega da solo: 0,5 piano, 2 di corsa.
PLANE_SIZEscript.js1.2La grandezza dell’aeroplanino in volo.
LOOP_SIZEscript.js1La grandezza del giro della morte.
DODGEscript.js56Di quanti pixel si scansano i blocchi quando l’aeroplanino li sfiora.
BANKscript.js0.6Quanto l’aeroplanino si inclina nelle curve: 0 resta dritto.
DASHscript.js9La lunghezza di ogni trattino della scia, in pixel.
SCRUBscript.js0.9Quanti secondi impiega l’aeroplanino a raggiungere lo scroll: 0 lo segue subito.
--rossostyle.css#d2412fIl rosso della posta aerea: righe del foglio, scia, bandierina e timbri.

Provali nel Playground

Quando usarla

Per una pagina che accompagna chi legge da un punto a un altro: un servizio di spedizioni o di consegne, una newsletter, un invito, un modulo di contatto che «parte», un’app di messaggi, una cartoleria, una pagina «come funziona» che finisce con la consegna.

Sul telefono

La stessa animazione con misure adattate: il foglio si piega sotto il titolo, i blocchi sono più larghi e l’aeroplanino, più piccolo, vola nella striscia libera accanto a loro; il giro della morte è più piccolo, la cassetta sta sopra il testo finale, così la scia non passa sulle parole. I blocchi si scansano un po’ meno.

Con il movimento ridotto

Niente piegatura, niente volo e niente scorrimento morbido: l’aeroplanino è già piegato in cima e compare in dissolvenza, la scia è già tutta disegnata fino alla cassetta, la cassetta è chiusa con la bandierina alzata e il timbro «Delivered» è già al suo posto. I testi compaiono solo in dissolvenza e i blocchi restano fermi.

Trappole

  • Ordinare le facce solo per la profondità del loro centro sbagliava le alette piegate: mentre il foglio si chiudeva a metà sparivano dietro alla faccia su cui erano appoggiate. Ora si ordinano prima i pannelli (metà e ali) e poi, su ogni pannello, la pila di carta secondo da che parte la si guarda.
  • Con le pieghe a 180° esatti le facce sovrapposte stanno sullo stesso piano e sfarfallano. Gli angoli si fermano a 177° e 173°: resta uno spessore che non si vede ma basta a tenerle separate.
  • Lo spazio del giro della morte va alzato prima di misurare la pagina: senza, il giro finiva sotto la cassetta, lo scroll del fondo veniva schiacciato e l’aeroplanino usciva dallo schermo verso il basso. Lo script dà alla sezione l’altezza del giro più lo scroll che gli serve, e solo dopo misura.
  • Un evaluate di Playwright che restituisce gsap.globalTimeline.timeScale(k) si blocca: il valore restituito è la timeline intera da copiare. Nelle prove il rallentatore si mette in un addInitScript.
  • La scia tratteggiata non si può scoprire col suo stroke-dashoffset, già usato dal tratteggio: si scopre la maschera, un tracciato uguale con un solo trattino lungo quanto tutto.

Librerie

GSAP 3.15.0, Lenis 1.3.26, Fraunces (font variabile) 5.3.0, Mona Sans (font variabile) 5.3.0.

Compressi con gzip, i tre file della demo pesano 17 KB; le librerie: GSAP + ScrollTrigger 45 KB, Lenis 5,3 KB.

Collaudo

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