Vai al contenuto
animorio
EN
Tutti i componenti

Le etichette dell'etichettatrice

Etichette, Testo, TransizioniCanvas, GSAPImpegnativaPeso compresso: Demo 20 KBGSAP 28 KBGratisScarica lo zip

Un campo per le etichette fatto con una vecchia etichettatrice a rilievo: scrivendo, la ruota delle lettere gira, il pomello scende e ogni lettera viene goffrata su un nastro di plastica lucida che esce dalla macchina, bianca dove la plastica si stira. Invio fa scattare la lama: l'etichetta tagliata vola sulla scatola di cartone e gli angoli le si arricciano un poco. Toccata, un'etichetta si stacca da un angolo e si accartoccia via. Tre nastri da scegliere: rosso, blu e nero.

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 label maker tags</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>
  <main class="stage">
    <!-- the tags of a box, made with an old embossing label maker: typing turns the wheel and presses every letter
         into a strip of glossy plastic tape that comes out of the machine, the letters white where the plastic is
         stretched. Enter (or the red lever) cuts the tape and the label flies onto the box, its corners curling a
         little; a label tapped is peeled off and crumpled away. The labels and the tape are painted by the script -->
    <div class="maker" data-maker data-autoclic>
      <p class="maker__ask" id="maker-ask">Label this box</p>
      <ul class="board" aria-labelledby="maker-ask" data-board></ul>

      <div class="bench" data-bench>
        <div class="bench__track" aria-hidden="true" data-track><span class="bench__ruler"></span></div>
        <span class="bench__ghost" aria-hidden="true" data-ghost>Type a label</span>
        <span class="bench__caret" aria-hidden="true" data-caret></span>
        <canvas class="bench__tape" aria-hidden="true" data-tape></canvas>

        <!-- the label maker, seen from above: the wheel of letters with its press knob, the pointer, the snout the
             tape comes out of, the red cutter lever, the window on the tape cartridge -->
        <svg class="machine" viewBox="0 0 200 124" aria-hidden="true" focusable="false" data-machine>
          <defs>
            <filter id="mk-soft" x="-20%" y="-200%" width="140%" height="500%"><feGaussianBlur stdDeviation="4.5"/></filter>
            <filter id="mk-softer" x="-50%" y="-50%" width="200%" height="200%"><feGaussianBlur stdDeviation="1.6"/></filter>
            <linearGradient id="mk-body" x1="0" y1="0" x2="0" y2="1">
              <stop class="st-body-hi" offset="0"/>
              <stop class="st-body" offset="0.42"/>
              <stop class="st-body-deep" offset="1"/>
            </linearGradient>
            <linearGradient id="mk-rim" x1="0" y1="0" x2="0" y2="1">
              <stop offset="0" stop-color="#ffffff" stop-opacity="0.34"/>
              <stop offset="0.35" stop-color="#ffffff" stop-opacity="0.04"/>
              <stop offset="1" stop-color="#ffffff" stop-opacity="0"/>
            </linearGradient>
            <linearGradient id="mk-chrome" x1="0" y1="0" x2="1" y2="1">
              <stop offset="0" stop-color="#fbfcfd"/>
              <stop offset="0.28" stop-color="#a6acb4"/>
              <stop offset="0.5" stop-color="#eef0f2"/>
              <stop offset="0.74" stop-color="#7b818a"/>
              <stop offset="1" stop-color="#d6dade"/>
            </linearGradient>
            <linearGradient id="mk-chrome-v" x1="0" y1="0" x2="0" y2="1">
              <stop offset="0" stop-color="#f4f6f8"/>
              <stop offset="0.5" stop-color="#9aa0a8"/>
              <stop offset="1" stop-color="#d9dde1"/>
            </linearGradient>
            <radialGradient id="mk-disc" cx="0.42" cy="0.36" r="0.7">
              <stop offset="0" stop-color="#34353a"/>
              <stop offset="1" stop-color="#101113"/>
            </radialGradient>
            <radialGradient id="mk-knob" cx="0.36" cy="0.3" r="0.78">
              <stop offset="0" stop-color="#ffffff"/>
              <stop offset="0.22" stop-color="#e3e6e9"/>
              <stop offset="0.62" stop-color="#9ba2aa"/>
              <stop offset="1" stop-color="#5a6068"/>
            </radialGradient>
            <linearGradient id="mk-red" x1="0" y1="0" x2="0" y2="1">
              <stop class="st-red-hi" offset="0"/>
              <stop class="st-red" offset="0.55"/>
              <stop class="st-red-deep" offset="1"/>
            </linearGradient>
            <radialGradient id="mk-glare" cx="0.3" cy="0.25" r="0.8">
              <stop offset="0" stop-color="#ffffff" stop-opacity="0.55"/>
              <stop offset="0.45" stop-color="#ffffff" stop-opacity="0.06"/>
              <stop offset="1" stop-color="#ffffff" stop-opacity="0"/>
            </radialGradient>
            <clipPath id="mk-window"><circle r="17.6"/></clipPath>
          </defs>

          <ellipse class="mk-shadow" cx="104" cy="114" rx="90" ry="7" filter="url(#mk-soft)"/>

          <g data-jolt>
            <!-- the snout: the tape comes out of its left end, between two chrome jaws -->
            <path class="mk-snout" d="M46 44H14C8.5 44 6 47 6 52V72C6 77 8.5 80 14 80H46Z"/>
            <path class="mk-snout-rim" d="M46 44.6H14C9 44.6 6.6 47.4 6.6 52"/>
            <rect class="mk-jaw" x="5" y="44.5" width="5.4" height="7" rx="1.6"/>
            <rect class="mk-jaw" x="5" y="72.5" width="5.4" height="7" rx="1.6"/>
            <rect class="mk-slot" x="4.4" y="50.6" width="2.2" height="22.8" rx="1"/>

            <!-- the cutter lever, turning round its pin -->
            <g transform="translate(42 93)">
              <g data-lever>
                <path class="mk-arm" d="M2 -3.2L-26 -2.4C-28.4 -2.3 -29 -1 -29 0.6V1.6C-29 3 -28.4 4 -26 4L2 3.6Z"/>
                <rect x="-38.5" y="-6.5" width="14" height="13.5" rx="3.4" fill="url(#mk-red)"/>
                <path class="mk-paddle-shine" d="M-36.4 -4.4H-27"/>
              </g>
              <circle class="mk-pin" r="3.6"/>
            </g>

            <!-- the body -->
            <path class="mk-body" d="M62 10H160C182 10 196 30 196 62C196 94 182 114 160 114H62C44 114 32 99 32 82V42C32 25 44 10 62 10Z"/>
            <path class="mk-body-rim" d="M62 10H160C182 10 196 30 196 62C196 94 182 114 160 114H62C44 114 32 99 32 82V42C32 25 44 10 62 10Z"/>
            <path class="mk-body-edge" d="M196 62C196 94 182 114 160 114H62C44 114 32 99 32 82"/>

            <!-- ribs of the grip -->
            <g class="mk-ribs">
              <path d="M184.5 46V78"/>
              <path d="M188.5 48V76"/>
              <path d="M192.2 51V73"/>
            </g>

            <!-- the window on the cartridge: the roll of tape turns as the tape is fed -->
            <g transform="translate(160 62)">
              <circle class="mk-recess" r="19.5"/>
              <g clip-path="url(#mk-window)">
                <g data-coil>
                  <g data-coil-spin>
                    <circle class="mk-coil" r="15.4" data-coil-fill/>
                    <circle class="mk-wrap" r="13.6"/>
                    <circle class="mk-wrap" r="11.8"/>
                    <circle class="mk-wrap" r="10"/>
                    <circle class="mk-hub" r="7.4"/>
                    <path class="mk-spoke" d="M0 -7V-3M6.06 3.5L2.6 1.5M-6.06 3.5L-2.6 1.5"/>
                    <circle class="mk-hole" r="2.6"/>
                  </g>
                </g>
                <g data-coil>
                  <g data-coil-spin>
                    <circle class="mk-coil" r="15.4" data-coil-fill/>
                    <circle class="mk-wrap" r="13.6"/>
                    <circle class="mk-wrap" r="11.8"/>
                    <circle class="mk-wrap" r="10"/>
                    <circle class="mk-hub" r="7.4"/>
                    <path class="mk-spoke" d="M0 -7V-3M6.06 3.5L2.6 1.5M-6.06 3.5L-2.6 1.5"/>
                    <circle class="mk-hole" r="2.6"/>
                  </g>
                </g>
                <circle r="17.6" fill="url(#mk-glare)"/>
              </g>
              <circle class="mk-bezel" r="18.8"/>
            </g>

            <!-- the wheel of letters, its chrome ring and the press knob in the middle -->
            <g transform="translate(88 62)">
              <circle class="mk-ring-shadow" r="51" cy="1.6" filter="url(#mk-softer)"/>
              <circle r="50" fill="url(#mk-chrome)"/>
              <g class="mk-knurl" data-knurl></g>
              <circle class="mk-disc" r="45.4" fill="url(#mk-disc)"/>
              <g data-wheel></g>
              <circle class="mk-groove" r="29.6"/>
              <circle class="mk-groove-hi" r="30.6"/>
              <g data-knob>
                <circle class="mk-knob-shadow" r="26" cy="2.2" filter="url(#mk-softer)"/>
                <circle r="25" fill="url(#mk-knob)"/>
                <circle class="mk-knob-line" r="21.5"/>
                <circle class="mk-knob-line mk-knob-line--dark" r="17"/>
                <circle class="mk-knob-line" r="12.5"/>
                <path class="mk-knob-shine" d="M-15 -12A19 19 0 0 1 4 -18.6"/>
              </g>
            </g>

            <!-- the pointer over the wheel: the letter under it is the one pressed -->
            <path class="mk-pointer-base" d="M81.2 3.2H94.8L92.4 9.4H83.6Z"/>
            <path d="M83.4 4.6H92.6L88 16.6Z" fill="url(#mk-red)"/>
          </g>
        </svg>

        <input class="bench__input" id="maker-input" type="text" aria-label="New label" aria-describedby="maker-hint" autocomplete="off" autocapitalize="characters" autocorrect="off" spellcheck="false" enterkeyhint="done" data-input>
        <button class="bench__cut" type="button" aria-label="Cut the label" data-cut></button>
      </div>

      <div class="maker__foot">
        <p class="maker__hint" id="maker-hint" data-hint></p>
        <fieldset class="tapes" data-tapes>
          <legend class="sr">Tape colour</legend>
          <span class="tapes__name" aria-hidden="true">Tape</span>
          <label class="pick" style="--t: var(--red)"><input type="radio" name="maker-tape" value="red" checked><span class="pick__tape">RED</span></label>
          <label class="pick" style="--t: var(--blue)"><input type="radio" name="maker-tape" value="blue"><span class="pick__tape">BLUE</span></label>
          <label class="pick" style="--t: var(--black)"><input type="radio" name="maker-tape" value="black"><span class="pick__tape">BLACK</span></label>
        </fieldset>
      </div>
      <p class="sr" aria-live="polite" data-live></p>
    </div>
  </main>

  <!-- where a label peeled off is crumpled and thrown away -->
  <canvas class="wads" aria-hidden="true" data-wads></canvas>

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

34 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 etichette dell'etichettatrice» da Animorio e adattala al mio sito

Cosa fa

Su un fondo bianco la scritta Label this box, una striscia di cartone kraft con attaccate tre etichette a rilievo, FRAGILE rossa, KITCHEN blu e BOOKS nera, lucide, con le lettere bianche in rilievo e due angoli appena sollevati. Sotto, un'etichettatrice d'epoca vista dall'alto, in plastica grafite e cromo: la ruota delle lettere con il pomello al centro e una freccia rossa in cima, la finestra sul rotolo del nastro, il beccuccio da cui esce il nastro e una leva rossa per tagliare; accanto, una scanalatura chiara con un righello e la scritta Type a label. Scrivendo, per ogni lettera la ruota gira dalla parte più corta finché la lettera è sotto la freccia, il nastro avanza fuori dal beccuccio, il rotolo nella finestra gira, il pomello scende e la lettera sale dalla plastica e si sbianca. Invio, una virgola o la leva fanno uscire un po' di nastro, la leva scatta, la lama lampeggia e l'etichetta tagliata si alza, passa fra la macchina e la scatola e sale al suo posto in fondo alla fila; batte, si schiaccia appena e gli angoli si arricciano piano. Toccata (o con Invio, Canc, o due volte il tasto indietro nel campo vuoto), un'etichetta solleva un angolo che si ripiega mostrando il retro, si stacca, si accartoccia in una pallina che rotola via e cade, e le altre scivolano a chiudere il vuoto. Sotto, Tape e tre pezzetti di nastro, RED, BLUE e BLACK: quello scelto sporge, e il rotolo nella finestra viene cambiato.

Come funziona

Un campo vero sotto la macchina

Sopra tutto il banco c'è un input vero, trasparente, a 16 pixel: lo tocca il dito, lo legge lo screen reader. Il testo viene ripulito a ogni tasto (maiuscole, niente accenti, solo i caratteri della ruota) e resta la verità: la macchina lo insegue una lettera alla volta, con un lavoro alla volta in una timeline GSAP, più veloce quando è indietro (timeScale secondo le lettere che aspettano). Le etichette sono pulsanti Peel off, i nastri radio, e una regione aria-live dice cosa succede.

La ruota e il colpo

La ruota è un SVG con quaranta caratteri in cerchio, le teste verso fuori. Per ogni lettera gira della differenza più corta (normalizzata fra -180 e 180 gradi) con back.out, così si sente lo scatto; la lettera sotto la freccia si accende. Poi il nastro avanza di PITCH pixel, il rotolo gira di quanto nastro è uscito, il pomello scala a 0,88 e la macchina sobbalza di un pixel.

Il rilievo dipinto

Nastro ed etichette sono dipinti su canvas dalla stessa funzione: la plastica con un gradiente, la lucentezza sopra e un filo di luce in alto. Ogni lettera è tre passate: un'ombra sfocata in basso a destra, un bordo di luce in alto a sinistra e la lettera schiarita verso il bianco quanto è stata premuta (p da 0 a 1), con l'ammaccatura della matrice mentre scende. Le lettere stanno a passo fisso come sul nastro vero, e nel canvas usano l'asse di larghezza di Archivo (fontStretch), o se manca un restringimento.

Gli angoli che si arricciano

Ogni angolo ha una misura c e un angolo a: il nastro perde il triangolo fino alla piega e la punta, vista dall'alto, torna verso la piega di cos(a). Fino a 90 gradi si vede il davanti, che prende luce, oltre si vede il retro; sotto, l'ombra dell'angolo sollevato. Atterrata un'etichetta, gli angoli passano da 0 al loro valore a riposo; il puntatore ne solleva uno un po' di più, pronto da staccare.

Il volo e la pallina

Tagliata, l'etichetta entra subito nella fila (le altre fanno posto con FLIP) e parte dal punto del nastro: sale nello spazio fra macchina e scatola, va di lato e sale al suo posto da sotto, così non passa mai sopra un'altra etichetta. Staccata, diventa una griglia di triangoli su un canvas sopra la pagina: ogni punto va dalla sua posizione sull'etichetta piatta a un punto di una sfera stropicciata da un rumore continuo, prima l'angolo preso; ogni triangolo è disegnato con il suo pezzo d'etichetta (una trasformazione affine per triangolo), ombreggiato secondo la sua normale e, se si è girato, con il colore del retro.

Valori da cambiare

NomeFileDi partenzaCosa cambia
STARTscript.js[['FRAGILE', 'red'], ['KITCHEN', 'blue'], ['BOOKS', 'black']]Le etichette sulla scatola all'apertura della pagina, ognuna col suo nastro: red, blue o black.
MAXscript.js6Quante etichette stanno sulla scatola.
LONGESTscript.js12Quante lettere può avere al massimo un'etichetta (la scanalatura è lunga così).
PITCHscript.js11.5Lo spazio di ogni lettera sul nastro, in pixel.
PRESSscript.js0.42I secondi che la macchina impiega per una lettera: la ruota gira, il nastro avanza, il pomello scende.
CURLscript.js6Quanto si arricciano gli angoli di un'etichetta, in pixel.
FLIGHTscript.js0.8I secondi del volo di un'etichetta dalla macchina alla scatola.
TOSSscript.js1Quanto forte viene buttata via un'etichetta accartocciata (0 la lascia cadere).

Provali nel Playground

Quando usarla

Per le etichette di un'app di traslochi o di magazzino, le categorie di un archivio, le parole chiave di un portfolio o di un blog fatto a mano, le etichette di un negozio di oggetti vintage o di cancelleria: dove il campo delle etichette può essere il pezzo che si ricorda.

Sul telefono

La macchina si rimpicciolisce all'82% e la scanalatura le sta accanto; la scatola ha due righe di posto, così la quarta etichetta non spinge giù la macchina. Toccando il banco si apre la tastiera (la casella è a 16 pixel, così Safari su iPhone non ingrandisce, le maiuscole sono accese e la correzione spenta); il tasto della tastiera o la leva rossa tagliano. Un tocco su un'etichetta la stacca: al posto del passaggio del puntatore, l'angolo si solleva quando la si tocca.

Con il movimento ridotto

La ruota va subito alla lettera e il nastro esce senza scivolare; le lettere compaiono in dissolvenza, l'etichetta tagliata compare in dissolvenza al suo posto sulla scatola e quella staccata svanisce, senza volo né pallina; il rotolo si cambia in dissolvenza e niente trema. La macchina resta tutta da usare.

Trappole

  • Il nastro esce a sinistra, non a destra: chi esce per primo va più lontano, e con l'uscita a destra la parola si leggerebbe al contrario.
  • Scrivere più in fretta della macchina: il testo nel campo è la verità e la macchina lo insegue con un lavoro alla volta, accelerando secondo quanto è indietro. Una virgola che arriva mentre l'etichetta prima viene ancora tagliata univa le due parole: i tagli in attesa stanno in una coda, e l'etichetta che si sta tagliando conta già per il limite e per i doppioni.
  • Il volo passava sopra le altre etichette o sopra le lettere della ruota (testo sopra testo): ora sale nello spazio fra macchina e scatola, va di lato e sale al suo posto da sotto, dove non c'è niente.
  • Le ombre del canvas (shadowOffset, shadowBlur) non seguono la trasformazione: vanno moltiplicate per devicePixelRatio, altrimenti sullo schermo retina sono la metà.
  • La pallina all'inizio era fatta di schegge: un rumore casuale punto per punto rompe la carta. Con un rumore continuo i punti vicini si piegano insieme e vengono pieghe; i triangoli si allargano di mezzo pixel, se no fra uno e l'altro si vede una riga.
  • L'angolo ripiegato spariva quando la pallina prendeva il posto dell'etichetta: la trama della pallina va dipinta con l'angolo com'è in quel momento.

Librerie

GSAP 3.15.0, Archivo (font variabile) 5.3.0.

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

Collaudo

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