Vai al contenuto
animorio
EN
Torna alla libreria

Le schede lanciate

Hover, FisicaGSAPFacilePeso compresso: Demo 5,2 KBGSAP + Inertia 31 KBGratisScarica lo zip

Una bacheca di cartoline. Basta sfiorarne una col puntatore e l’immagine viene lanciata dalla parte in cui andava il puntatore, veloce quanto lui, si torce un poco e torna al suo posto. Più veloce è il passaggio, più lontano vola; sul telefono un tocco la lancia in una direzione a caso.

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>Tossed cards</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource/instrument-serif@5.3.0/index.css">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource/instrument-serif@5.3.0/400-italic.css">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/dm-sans@5.3.0/index.css">
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <header class="bar">
    <a class="brand" href="#">Wish You Were</a>
    <nav class="bar__nav" aria-label="Sections">
      <a href="#">Issues</a>
      <a href="#">Shop</a>
      <a href="#">About</a>
    </nav>
  </header>

  <main class="board">
    <div class="intro">
      <h1 class="intro__title">Postcards from places <em>that don’t exist.</em></h1>
      <p class="intro__hint" data-hint>Brush past a card: it flies off and comes back.</p>
    </div>

    <!-- each card: the figure keeps the place on the board, the inner part is what gets thrown -->
    <div class="cards">
      <figure class="card" data-card style="--r: -4deg; --y: 10px">
        <div class="card__art" data-toss>
          <svg viewBox="0 0 300 400" aria-hidden="true">
            <rect width="300" height="400" fill="#1d2b4a"/>
            <circle cx="205" cy="96" r="34" fill="#f3e7c9"/>
            <path d="M0 250 70 170 120 215 175 140 240 220 300 180V280H0Z" fill="#121b30"/>
            <rect y="276" width="300" height="124" fill="#1a3150"/>
            <path d="M160 300h90M175 320h60M190 340h30" stroke="#f3e7c9" stroke-width="5" stroke-linecap="round" opacity="0.5"/>
          </svg>
          <figcaption>Greetings from <span>Lago Nero</span></figcaption>
        </div>
      </figure>
      <figure class="card" data-card style="--r: 3deg; --y: -6px">
        <div class="card__art" data-toss>
          <svg viewBox="0 0 300 400" aria-hidden="true">
            <rect width="300" height="400" fill="#ffd9a0"/>
            <circle cx="150" cy="215" r="74" fill="#ff6b35"/>
            <rect y="232" width="300" height="168" fill="#2a6f97"/>
            <path d="M30 262h90M160 262h110M60 292h70M170 292h80M20 322h120M180 322h60M70 352h150" stroke="#7fb6d5" stroke-width="6" stroke-linecap="round"/>
          </svg>
          <figcaption>Greetings from <span>Saltmarsh</span></figcaption>
        </div>
      </figure>
      <figure class="card" data-card style="--r: -2deg; --y: 18px">
        <div class="card__art" data-toss>
          <svg viewBox="0 0 300 400" aria-hidden="true">
            <rect width="300" height="400" fill="#ffc2b4"/>
            <circle cx="88" cy="108" r="30" fill="#fff1d6"/>
            <path d="M0 250C70 190 130 200 180 240S270 260 300 230V400H0Z" fill="#f2937a"/>
            <path d="M0 310C60 270 120 280 170 300S260 330 300 300V400H0Z" fill="#e86f51"/>
            <path d="M0 360C80 330 150 350 210 370S280 380 300 360V400H0Z" fill="#c74b37"/>
          </svg>
          <figcaption>Greetings from <span>Dune Nine</span></figcaption>
        </div>
      </figure>
      <figure class="card" data-card style="--r: 5deg; --y: 0px">
        <div class="card__art" data-toss>
          <svg viewBox="0 0 300 400" aria-hidden="true">
            <rect width="300" height="400" fill="#dfe9d1"/>
            <path d="M40 330V190a50 50 0 0 1 100 0v140M160 330V190a50 50 0 0 1 100 0v140" fill="none" stroke="#2f6b4f" stroke-width="10"/>
            <path d="M90 330V230M210 330V230" stroke="#2f6b4f" stroke-width="6"/>
            <path d="M60 330c10-40 40-50 50-80 10 30 0 60-10 80zM180 330c0-50 30-60 40-90 14 40 4 70-10 90z" fill="#3f8a5f"/>
            <rect y="330" width="300" height="70" fill="#b9cfa4"/>
          </svg>
          <figcaption>Greetings from <span>Glasshouse</span></figcaption>
        </div>
      </figure>
      <figure class="card" data-card style="--r: -5deg; --y: -8px">
        <div class="card__art" data-toss>
          <svg viewBox="0 0 300 400" aria-hidden="true">
            <rect width="300" height="400" fill="#2a1f4d"/>
            <path d="M60 70l4 10 10 4-10 4-4 10-4-10-10-4 10-4zM230 120l3 7 7 3-7 3-3 7-3-7-7-3 7-3zM170 55l2 5 5 2-5 2-2 5-2-5-5-2 5-2z" fill="#ffcf5c"/>
            <rect x="20" y="210" width="260" height="80" rx="16" fill="#4b3a86"/>
            <rect x="40" y="228" width="40" height="28" rx="5" fill="#ffcf5c"/>
            <rect x="100" y="228" width="40" height="28" rx="5" fill="#ffcf5c"/>
            <rect x="160" y="228" width="40" height="28" rx="5" fill="#ffcf5c"/>
            <rect x="220" y="228" width="40" height="28" rx="5" fill="#ffcf5c"/>
            <path d="M0 300h300M0 318h300" stroke="#8a78c9" stroke-width="5"/>
          </svg>
          <figcaption>Greetings from <span>Night Train</span></figcaption>
        </div>
      </figure>
      <figure class="card" data-card style="--r: 2deg; --y: 14px">
        <div class="card__art" data-toss>
          <svg viewBox="0 0 300 400" aria-hidden="true">
            <rect width="300" height="400" fill="#2f7fd1"/>
            <path d="M20 330q30-16 60 0t60 0 60 0 60 0 40 0M20 360q30-16 60 0t60 0 60 0 60 0 40 0" fill="none" stroke="#bfe0ff" stroke-width="6" stroke-linecap="round"/>
            <ellipse cx="110" cy="170" rx="58" ry="44" fill="#ffd23f" transform="rotate(-18 110 170)"/>
            <ellipse cx="200" cy="230" rx="50" ry="38" fill="#ffd23f" transform="rotate(14 200 230)"/>
            <path d="M150 120c20-30 50-30 70-20-20 20-45 26-70 20z" fill="#3a8c4a"/>
            <path d="M236 190c16-24 40-26 56-18-16 18-36 22-56 18z" fill="#3a8c4a"/>
          </svg>
          <figcaption>Greetings from <span>Lemon Coast</span></figcaption>
        </div>
      </figure>
      <figure class="card" data-card style="--r: -3deg; --y: 4px">
        <div class="card__art" data-toss>
          <svg viewBox="0 0 300 400" aria-hidden="true">
            <rect width="300" height="400" fill="#cfe6f5"/>
            <path d="M0 260 90 120 150 200 210 110 300 250V400H0Z" fill="#ffffff"/>
            <path d="M90 120 120 260H0ZM210 110 240 250H300Z" fill="#a9c8e0" opacity="0.7"/>
            <path d="M120 300l40-34 40 34v40h-80z" fill="#d9483b"/>
            <rect x="148" y="312" width="22" height="28" fill="#7a2620"/>
            <rect y="340" width="300" height="60" fill="#ffffff"/>
          </svg>
          <figcaption>Greetings from <span>Snow Hut</span></figcaption>
        </div>
      </figure>
    </div>
  </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/InertiaPlugin.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.

40 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 «Le schede lanciate» da Animorio e adattala al mio sito

Cosa fa

La bacheca di una rivista inventata di cartoline, Wish You Were: il titolo «Postcards from places that don’t exist.», con la seconda metà in corsivo rosso, e sette cartoline di luoghi inventati, ognuna con la sua illustrazione e la scritta «Greetings from…», un poco storte e un poco fuori riga. All’arrivo vengono distribuite sulla bacheca una dopo l’altra, ruotando e rimbalzando. Passando col puntatore su una cartolina, l’immagine parte nella direzione del puntatore con la sua velocità, rallenta e torna esattamente al suo posto, mentre si torce di qualche grado e si raddrizza. Ogni cartolina ha un suo peso: le più pesanti volano più lontano e si torcono di più. Ripassando sopra una cartolina ancora in volo, il nuovo lancio riparte da dove si trova.

Come funziona

Il posto e l’immagine

Ogni cartolina è un figure, girato e spostato di poco con due variabili CSS: è il suo posto sulla bacheca e non si muove. Dentro c’è l’immagine con la cornice e la scritta, ed è lei che vola, così il posto resta quello anche a metà lancio.

La velocità del puntatore

Lo script tiene l’ultimo spostamento del puntatore fra un evento e il successivo. Quando il puntatore entra in una cartolina, quello spostamento moltiplicato per PUSH, e tenuto entro MAX pixel al secondo, diventa la velocità del lancio, moltiplicata ancora per il peso della cartolina (WEIGHTS).

Il lancio con InertiaPlugin

Il lancio è un solo tween: inertia con una velocità per x e una per y e una fine a 0. Il plugin calcola da solo quanto dura e la curva: la cartolina parte alla velocità data, rallenta e atterra esattamente dov’era. RESISTANCE dice quanto in fretta frena, e la timeline gira PACE volte più veloce.

La torsione

Nello stesso momento parte un secondo tween sulla rotazione: fino a metà di WOBBLE gradi a caso, in TWIST secondi, e indietro con yoyo. Tutti e due hanno overwrite auto, quindi un nuovo lancio prende il posto di quello in corso senza scatti.

Quale cartolina

Non si ascolta l’entrata in ogni cartolina: un solo ascoltatore di pointermove sulla finestra guarda in quale cartolina sta il puntatore e lancia quando cambia. Così un passaggio veloce su tre cartoline le lancia tutte e tre, una volta ciascuna.

Valori da cambiare

NomeFileDi partenzaCosa cambia
PUSHscript.js14Quanto dell’ultimo spostamento del puntatore va nel lancio: pixel al secondo per ogni pixel.
MAXscript.js900Il lancio più veloce, in pixel al secondo.
WOBBLEscript.js30La torsione più ampia, in gradi, metà per parte.
TWISTscript.js0.4I secondi della torsione all’andata, e gli stessi al ritorno.
PACEscript.js1.2Quanto più veloce dei suoi tempi gira il lancio.
RESISTANCEscript.js100Quanto in fretta frena una cartolina lanciata: più alto, voli più corti.
TAPscript.js650Sul telefono, quanto forte un tocco lancia una cartolina, in pixel al secondo.
WEIGHTSscript.js1, 0.8, 1.25, 0.9, 1.15, 1, 0.85Il peso di ogni cartolina, in ordine: più pesante vola più lontano e si torce di più.
--cardstyle.cssclamp(140px, 14vw, 214px)La larghezza di una cartolina.

Provali nel Playground

Quando usarla

Per qualunque griglia di schede, copertine, prodotti o foto che deve sembrare viva al passaggio del mouse: un portfolio, un negozio, una galleria. Funziona meglio con schede ben distanziate e un fondo pieno; su schede attaccate fra loro le lanciate coprono le vicine.

Sul telefono

Le cartoline vanno su due colonne e la pagina scorre. Un tocco lancia la cartolina in una direzione a caso, quasi sempre verso l’alto, a 650 pixel al secondo; lo scorrimento col dito non lancia niente.

Con il movimento ridotto

Le cartoline sono già al loro posto all’arrivo e non volano: il puntatore e il dito non le spostano.

Trappole

  • Le cartoline girate vicino ai bordi, e quelle in volo, allargano la pagina: al telefono si poteva scorrere di lato di 9 pixel. html e body hanno overflow-x: clip, che taglia senza creare un riquadro che scorre.
  • Con un ascoltatore di pointerenter su ogni cartolina, un evento creato da uno script con bubbles: true, come quelli di un pilota automatico, risalirebbe dai figli e farebbe partire un lancio a ogni disegno attraversato. Si guarda invece, a ogni movimento, in quale cartolina sta il puntatore.
  • Il lancio con la fine a 0 parte dalla posizione in cui la cartolina si trova: per questo un secondo passaggio durante il volo non la teletrasporta, la rilancia.

Librerie

GSAP 3.15.0, InertiaPlugin (GSAP) 3.15.0, Instrument Serif 5.3.0, DM Sans (font variabile) 5.3.0.

Compressi con gzip, i tre file della demo pesano 5,2 KB; le librerie: GSAP + Inertia 31 KB.

Collaudo

Provata il 2 ottobre 2026

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

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