Vai al contenuto
animorio
EN
Tutti i componenti

La card del profumo

Card, Fisica, Hover, TestoCanvas, GSAP, Solo CSSImpegnativaPeso compresso: Demo 20 KBGSAP 28 KBGratisScarica lo zip

La card di un’acqua di profumo in una piccola profumeria: una boccetta di vetro sfaccettato piena a metà di profumo ambrato, col vaporizzatore d’oro, su una mensola di pietra davanti a un muro verde foglia di fico. La luce segue il puntatore: la boccetta si inclina verso di lei sullo spigolo della base, il profumo dentro resta in piano e ondeggia quando il vetro si muove, e ogni faccia del vetro piega quello che c’è dietro e prende la luce col suo angolo. Premendo il vaporizzatore, o Try a spray, parte una nuvola di goccioline che si arriccia nell’aria, e dalla nuvola le note del profumo si radunano goccia a goccia e si posano alla loro altezza: la nota di testa più in alto, quella di fondo più in basso. Poi svaniscono nell’ordine in cui svanisce un profumo sulla pelle.

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 perfume card</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/playfair@5.3.0/standard.css">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/playfair@5.3.0/standard-italic.css">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/mona-sans@5.3.0/wdth.css">
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <main class="stage">
    <!-- the card of a perfume in a small perfumery. In its picture a faceted glass bottle of amber perfume: the
         perfume leans as the bottle moves, the facets bend what is behind them and catch the light, which follows
         the pointer. A press on the atomizer, or Try a spray, throws a cloud of mist, and the notes of the perfume
         gather out of it and settle at their heights: the top note highest, the base note lowest. Then they fade in
         the order a perfume fades on the skin. The bottle, the mist and the light are drawn by the script -->
    <article class="scent" aria-labelledby="scent-name" data-scent data-autoclic>
      <div class="shot" data-shot>
        <canvas class="shot__canvas" role="img" aria-label="A faceted glass bottle of amber perfume with a gold atomizer, standing on dark stone" data-canvas></canvas>
        <div class="notes" aria-hidden="true">
          <p class="note note--top" data-note><span class="note__tier">Top</span><span class="note__name" data-word>Bergamot</span></p>
          <p class="note note--heart" data-note><span class="note__tier">Heart</span><span class="note__name" data-word>Fig leaf</span></p>
          <p class="note note--base" data-note><span class="note__tier">Base</span><span class="note__name" data-word>Cedar</span></p>
        </div>
        <button class="shot__nozzle" type="button" aria-label="Spray the perfume" data-nozzle></button>
      </div>

      <div class="scent__body">
        <p class="scent__kind">Atelier Ombrine · Eau de parfum</p>
        <div class="scent__head">
          <h2 class="scent__name" id="scent-name">Fig Hour</h2>
          <p class="scent__price" aria-live="off"><span class="sr" data-price-sr>€115</span><span class="price" aria-hidden="true" data-price>€115</span></p>
        </div>

        <div class="sizes" role="radiogroup" aria-label="Size" data-sizes>
          <span class="sizes__thumb" aria-hidden="true" data-thumb><span class="sizes__thumb-fill"></span></span>
          <button class="size" type="button" role="radio" aria-checked="false" tabindex="-1" data-size>30 ml</button>
          <button class="size" type="button" role="radio" aria-checked="true" tabindex="0" data-size>50 ml</button>
          <button class="size" type="button" role="radio" aria-checked="false" tabindex="-1" data-size>100 ml</button>
        </div>

        <div class="buy">
          <button class="pill pill--try" type="button" data-try>
            <span class="pill__icon" aria-hidden="true">
              <svg viewBox="0 0 24 24">
                <path d="M5.2 11.2h7.6a1.4 1.4 0 0 1 1.4 1.4v6.8a1.4 1.4 0 0 1-1.4 1.4H5.2a1.4 1.4 0 0 1-1.4-1.4v-6.8a1.4 1.4 0 0 1 1.4-1.4z"/>
                <path d="M7.6 11.2V8.4h2.8v2.8"/>
                <path d="M6.8 8.4V5.6h4.4v2.8"/>
                <g class="try__puff" data-puff>
                  <path d="M14.4 6.2h2.1"/>
                  <path d="M14.2 3.8l1.8-.9"/>
                  <path d="M14.2 8.6l1.8.9"/>
                  <path d="M18.6 6.2h1.6"/>
                  <path d="M18.1 2.5l1.3-.6"/>
                  <path d="M18.1 9.9l1.3.6"/>
                </g>
              </svg>
            </span>
            <span class="pill__label">Try a spray</span>
          </button>
          <button class="pill pill--add" type="button" data-add>
            <span class="pill__icon" aria-hidden="true">
              <svg class="add__glyph" viewBox="0 0 24 24" data-bag><path d="M5.4 8.4h13.2l-1 11.2a1.6 1.6 0 0 1-1.6 1.4H8a1.6 1.6 0 0 1-1.6-1.4z"/><path d="M9 10.6V7a3 3 0 0 1 6 0v3.6"/></svg>
              <svg class="add__glyph add__drop" viewBox="0 0 24 24" data-drop><path d="M12 9.2c1.5 2 2.3 3.3 2.3 4.4a2.3 2.3 0 0 1-4.6 0c0-1.1.8-2.4 2.3-4.4z"/></svg>
              <svg class="add__glyph add__tick" viewBox="0 0 24 24" data-tick><path d="M5.6 12.6l4.1 4.1 8.7-9.2"/></svg>
            </span>
            <span class="pill__label" data-label>Add to bag</span>
          </button>
        </div>
        <p class="sr" aria-live="polite" data-live></p>
      </div>
    </article>
  </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.

55 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 card del profumo» da Animorio e adattala al mio sito

Cosa fa

Su un fondo bianco una card bianca dagli angoli tondi. In alto la foto, disegnata dallo script: un muro verde scuro con una luce calda che lo schiarisce in alto a sinistra, una mensola di pietra e sopra una boccetta di profumo di vetro spesso, tagliata a ottagono, con le facce smussate tutt’intorno alla faccia piatta davanti. Dentro, il profumo ambrato fino a poco più di metà, più scuro in fondo, la cannuccia del vaporizzatore che scende fino in fondo e un’etichetta di carta col nome e il formato; in cima il collo, il collare d’oro rigato e la testa del vaporizzatore, col suo forellino a destra. Sotto la boccetta l’ombra e, dentro l’ombra, una macchia di luce ambrata: la luce passata attraverso il profumo. Col puntatore sopra la foto la luce va dove va il puntatore: la macchia chiara sul muro la segue, l’ombra gira dall’altra parte, la boccetta si inclina di qualche grado verso la luce alzandosi sullo spigolo della base, e il profumo resta in piano, ondeggia, sbatte e si calma. Ogni faccia smussata mostra il profumo e il bordo della mensola spostati, come fa il vetro spesso, e quella girata verso la luce si accende con un riflesso e un filo di colori, rosso da una parte e azzurro dall’altra. Premendo la testa del vaporizzatore (o Try a spray, o un tocco sulla foto) la testa scende, la boccetta rincula e il profumo sbatte; dal forellino esce un getto di goccioline finissime che si allarga, rallenta, si arriccia e lascia una nebbia leggera. Dalla nebbia una parte delle goccioline vola a disegnare tre parole: le goccioline formano le lettere e le lettere si condensano, da sfocate e sottili a nitide e piene, salendo di qualche pixel. Sono le note: Top Bergamot in alto, Heart Fig leaf a metà, Base Cedar in basso. Dopo qualche secondo la nota di testa evapora, lettera per lettera, in un filo di goccioline che sale; poi quella di cuore, e per ultima quella di fondo. Sotto la foto la marca, il nome Fig Hour, il prezzo, i formati 30, 50 e 100 ml (scegliendone uno la boccetta cresce o cala con un rimbalzo e il prezzo gira cifra per cifra), e i pulsanti Try a spray e Add to bag: una goccia ambrata cade nella borsa, poi In your bag con la spunta, e dopo qualche secondo torna com’era.

Come funziona

Il profumo tiene il suo volume

La cavità della boccetta è un ottagono e il profumo è la parte che sta sotto una retta: i punti p con m·p ≥ h, dove m è la normale della superficie. Per ogni angolo della superficie l’altezza h che lascia sotto esattamente l’area del profumo si trova per bisezione (24 passi, ritagliando l’ottagono con la retta e misurando l’area col metodo dei lacci): così il profumo, inclinandosi, si alza da una parte e si abbassa dall’altra senza crescere né calare. La superficie fra i due punti di taglio è piegata da un coseno, che ha area nulla e quindi non cambia il volume: è il secondo modo dell’onda, lo sciabordio.

Un pendolo dentro una molla

La boccetta si inclina verso la luce su una molla smorzata, e ruota sullo spigolo della base dalla parte verso cui pende (il perno cambia lato quando l’angolo passa per zero, quindi senza salti). L’angolo della superficie nella stanza è un pendolo smorzato poco: l’accelerazione della boccetta lo spinge fuori dal piano, poi torna oltre e ondeggia. Nel disegno l’angolo della superficie rispetto al vetro è quello nella stanza meno l’inclinazione della boccetta. Lo spruzzo dà un colpo indietro alla boccetta e al secondo modo, il cambio di formato anche.

Il vetro disegnato due volte

A ogni fotogramma si disegna in una tela nascosta quello che sta dietro e dentro il vetro: il muro e la mensola già disegnati, la base spessa che si accende del colore del profumo, la cavità, la cannuccia, il profumo con la sua luce. Poi, faccia per faccia, la tela vera si ritaglia sul poligono della faccia e ci copia quella tela: la faccia piatta ingrandita del 4,5% attorno al centro, ogni smusso spostato lungo la sua pendenza. Il profumo e il bordo della mensola si spezzano sugli spigoli come nel vetro spesso. Ogni faccia ha una normale in 3D: la luce del puntatore dà l’ombra (Lambert), il riflesso (Blinn, col vettore a metà fra luce e occhio) e sulla faccia più accesa un filo rosso e uno azzurro un capello più in là, come un prisma.

La nebbia in un vento a rotore

Lo spruzzo sono circa novecento goccioline in 0,22 secondi e una cinquantina di sbuffi morbidi, con velocità e direzioni sparse in un cono: frenano con l’aria (esponenziale), salgono piano e sono portate da un vento fatto col rotore di una somma di onde che scorrono nel tempo. Un vento così non ha sorgenti né pozzi: la nebbia si arriccia senza ammucchiarsi né sparire in un punto. Il vento entra piano, solo quando la goccia ha rallentato, così il getto resta dritto vicino all’ugello. Tutto è disegnato in modalità lighter, più chiaro vicino alla luce.

Le parole fatte di goccioline

Ogni nota è disegnata una volta in una tela nascosta, lettera per lettera, nel suo carattere e al suo posto (presi dal DOM con offsetLeft e offsetTop, che non sentono le trasformazioni di GSAP); i pixel pieni diventano i punti d’arrivo. Allo spruzzo per ogni parola partono fino a 270 goccioline con la nebbia: volano libere, poi una curva smoothstep le porta dal loro volo al loro punto, e la parola compare fatta di brillantini. Allora le lettere vere si condensano da sopra: GSAP le porta da sfocate, trasparenti e sottili (asse wght a 320) a nitide e piene (460), con un rimbalzo, mentre le goccioline si spengono. Per svanire si fa il contrario: le lettere salgono e si sfocano e dai punti della parola parte un filo di vapore.

Il prezzo e i formati

Il formato scelto è un radiogroup con le frecce: la pillola chiara sotto scorre col suo rimbalzo (posizione e larghezza in pixel, ricalcolate quando la card cambia misura), la boccetta cresce o cala con un elastico e il prezzo gira: le cifre vecchie salgono una dopo l’altra e le nuove arrivano da sotto. Add to bag fa cadere una goccia nella borsa, che si abbassa per prenderla, poi mostra la spunta e torna a riposo.

Valori da cambiare

NomeFileDi partenzaCosa cambia
TILTscript.js4Di quanti gradi la boccetta si inclina verso la luce.
SLOSHscript.js1Quanto il profumo ondeggia dentro quando la boccetta si muove (0 = resta fermo).
REFRACTscript.js8Di quanti pixel le facce smussate spostano quello che si vede attraverso.
FILLscript.js0.64Quanto è piena la boccetta, da 0,2 a 0,95.
MISTscript.js900Quante goccioline lancia uno spruzzo.
SPRAY_SPEEDscript.js560Quanto veloci escono le goccioline dall’ugello, in pixel al secondo.
SWIRLscript.js1Quanto l’aria arriccia la nebbia (0 = va dritta).
HOLDscript.js3.2I secondi in cui le note restano prima che cominci a svanire quella di testa.
DRYDOWNscript.js1.7I secondi fra una nota che svanisce e la successiva: testa, cuore, poi fondo.
PRICESscript.js[78, 115, 168]Il prezzo di ogni formato, 30, 50 e 100 ml.
SCALESscript.js[0.84, 1, 1.14]Quanto grande è disegnata la boccetta per ogni formato.
CURRENCYscript.js'€'La valuta prima del prezzo.
WORDSscript.js['Adding', 'In your bag']Add to bag mentre lavora e quando ha finito.

Provali nel Playground

Quando usarla

Per la scheda di un profumo, di una candela, di un olio o di un diffusore in un negozio online, dove le note sono la cosa da far capire; ovunque un prodotto in vetro debba sembrare vero (un liquore, un olio d’oliva, un siero) e una pagina di prodotto voglia un momento da provare prima del carrello.

Sul telefono

La card è larga 340 pixel, o lo schermo meno 32, e la foto si ridisegna alla misura vera; le note sono misurate sulla larghezza della foto (unità cqw), quindi restano al loro posto a ogni misura. Un tocco sulla foto spruzza; trascinando il dito di lato la luce segue il dito e la boccetta si inclina, e lasciando torna al suo posto (la pagina scorre in verticale come sempre). Le pillole sono alte 50 pixel e i formati 34. Sotto i 360 pixel il nome e le pillole si stringono un poco. La nebbia e le parole di goccioline sono le stesse del computer.

Con il movimento ridotto

La boccetta non si inclina e il profumo non ondeggia; la luce resta al suo posto. Lo spruzzo è una nebbia ferma che compare e se ne va in dissolvenza, senza goccioline che volano, e le note compaiono e svaniscono nello stesso ordine con una dissolvenza. La boccetta cambia misura di colpo e il prezzo nuovo compare in dissolvenza; le scritte dei pulsanti cambiano in dissolvenza e le pillole non si gonfiano.

Trappole

  • Nella prima versione la nebbia si fermava tutta alla stessa distanza dall’ugello e faceva un mucchio bianco come sabbia sopra la prima nota. Le goccioline ora partono con velocità molto diverse (dal 25% al 120%), muoiono prima, il vento a rotore è più forte quando hanno rallentato e gli sbuffi sono più trasparenti: il getto si allarga in una nebbia e non copre le parole.
  • Le goccioline dirette alle lettere, luminose fin dalla partenza, facevano un grumo di brillantini prima ancora di partire verso le parole: ora sono quasi spente mentre volano e si accendono solo arrivando (la luminosità segue il quadrato dell’avanzamento), e le lettere vere si condensano solo quando la parola di goccioline è già leggibile.
  • Il riflesso calcolato specchiando la luce sulla faccia (Phong) non si vedeva quasi mai: con la luce davanti al muro il raggio riflesso non arrivava quasi mai all’occhio. Con il vettore a metà fra luce e occhio (Blinn) lo smusso girato verso la luce si accende davvero.
  • La boccetta inclinata girando attorno al centro della base affondava uno spigolo nella pietra. Ora ruota sullo spigolo dalla parte verso cui pende, e l’altro si alza: il perno cambia lato quando l’angolo passa per zero, dove le due rotazioni coincidono, quindi non salta.
  • Il primo cambio di prezzo non girava: il prezzo nell’HTML era testo intero e non c’erano cifre da far salire. All’avvio lo script lo riscrive dai PRICES, una cifra per span.

Librerie

GSAP 3.15.0, Playfair (font variabile) 5.3.0, Mona Sans (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