Vai al contenuto
animorio
EN
Tutti i componenti

Il pulsante di velluto

Pulsanti, WebGL, HoverWebGL, GSAPImpegnativaPeso compresso: Demo 12 KBGSAP 28 KBGratisScarica lo zip

Il pulsante Add to bag di una boutique, rivestito di velluto bordeaux vero: il pelo ha un verso, e dove passa il puntatore si piega e lascia una scia più chiara o più scura, come la mano su un divano di velluto, che resta un momento e poi si rialza piano. Il pelo è un campo di direzioni spazzolato dal puntatore e illuminato in WebGL fibra per fibra, con una lucentezza che cambia con l’angolo del pelo. Al clic un’onda pettina tutto il velluto in un verso e la scritta diventa Added.

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 velvet button</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/bodoni-moda@5.3.0/opsz.css">
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <main class="stage">
    <!-- the velvet button: the Add to bag button of a boutique, covered in real velvet. The pile has a direction: where
         the pointer passes it bends and leaves a lighter or darker trail that slowly relaxes. A click sends a wave
         that combs the whole pile one way, the words say Added, then the velvet is smoothed back. The pile is a field
         of directions brushed by the pointer and lit by a WebGL shader; the words stay in HTML, on top -->
    <div class="velvet" data-velvet>
      <button class="velvet__btn" type="button" data-btn data-autoclic>
        <canvas class="velvet__cloth" aria-hidden="true" data-cloth></canvas>
        <span class="velvet__face" data-face="rest">
          <svg class="velvet__icon" viewBox="0 0 24 24" aria-hidden="true">
            <path d="M5.2 8.6h13.6l-1.1 11.1a1.2 1.2 0 0 1-1.2 1.1H7.5a1.2 1.2 0 0 1-1.2-1.1z"/>
            <path d="M9 10.8V7.2a3 3 0 0 1 6 0v3.6"/>
          </svg>
          <span>Add to bag</span>
        </span>
        <span class="velvet__face" data-face="done" aria-hidden="true">
          <svg class="velvet__icon" viewBox="0 0 24 24" aria-hidden="true">
            <path d="M5.2 8.6h13.6l-1.1 11.1a1.2 1.2 0 0 1-1.2 1.1H7.5a1.2 1.2 0 0 1-1.2-1.1z"/>
            <path d="M9 8.6V7.2a3 3 0 0 1 6 0v1.4"/>
            <path d="M9.4 14.6l1.9 1.9 3.5-3.7" pathLength="1" data-check/>
          </svg>
          <span>Added</span>
        </span>
      </button>
      <p class="sr" aria-live="polite" data-live></p>
    </div>
  </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.

18 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 «Il pulsante di velluto» da Animorio e adattala al mio sito

Cosa fa

Su un fondo nero, da solo, un pulsante alto 60 pixel e largo 320 rivestito di velluto bordeaux su un’imbottitura: il velluto si arrotonda sui bordi, dove prende una luce morbida di lato, e al centro è appena bombato, più chiaro in alto verso la lampada. Sopra, stampata color champagne, la scritta ADD TO BAG in maiuscolo spaziato, in Bodoni, con una piccola borsa disegnata. All’arrivo il velluto compare in dissolvenza, la scritta si stringe al suo posto e una mano invisibile passa una volta sul tessuto da sinistra a destra, lasciando una scia più chiara. Passando col mouse il pelo si piega nel verso del movimento: andando verso destra o verso il basso la scia è più chiara e lucida, verso sinistra o verso l’alto più scura e profonda, con i bordi sfilacciati come quelli veri. La scia resta ferma per un paio di secondi e poi si rialza piano fino a sparire. Premendo, il velluto affonda nell’imbottitura e il pelo si apre a raggiera intorno al dito. Al clic parte un’onda dal punto premuto: la cresta, con una piccola increspatura dietro, solleva il pelo e lo getta in fuori, con un filo di luce dalla parte della lampada, e dietro di lei tutto il velluto resta pettinato in un verso, più chiaro e rigato. Quando la cresta passa il centro la scritta diventa ADDED e nella borsa si disegna una spunta. Dopo 2,2 secondi un’onda più morbida parte dal bordo destro e liscia il velluto com’era, e la scritta torna ADD TO BAG.

Come funziona

Il pelo è un campo di direzioni

Lo script tiene, ogni 2 pixel del pulsante, un vettore: il verso in cui pende la fibra, e quanto è lungo dice quanto è stesa (0 dritta, 1 piatta). A riposo tutti pendono in giù di NAP, com’è tessuto il velluto. Il campo vive in due Float32Array e a ogni fotogramma in cui cambia sale sulla GPU come una texture piccolissima, due byte per cella, che la scheda video sfuma da una cella all’altra.

La mano spazzola

Ogni movimento del puntatore (con getCoalescedEvents, così una mano veloce non salta) è un segmento: le celle vicine vengono tirate verso il verso del segmento, lunghe LAY, con una campana piatta della distanza dal segmento (e alla meno q alla quarta), così la scia ha un bordo netto. La presa è 1 meno e alla meno lunghezza/5: una passata lunga stende il pelo del tutto, un tremolio lo piega appena. Il mouse sfiora (0,85), il mouse premuto e il dito schiacciano e sono più larghi; la pressione apre il pelo a raggiera intorno al punto.

Il pelo si rialza piano

A ogni fotogramma ogni cella torna verso il verso del velluto (tessuto in giù, o pettinato dall’onda) con un’esponenziale. Una cella appena spazzolata però tiene il segno: ha un valore di presa che si svuota in un terzo di RELAX e frena il ritorno finché c’è, così la scia resta ferma un momento e poi se ne va. Quando tutte le celle sono ferme e niente si muove, non si ridisegna niente.

La luce fibra per fibra

Lo shader disegna l’imbottitura dalla distanza da un rettangolo arrotondato (una pendenza negli ultimi 12 pixel e una bombatura leggera dall’alto in basso) e ne ricava la normale. La fibra è la normale inclinata secondo il campo. La lucentezza è quella anisotropa dei capelli (Kajiya e Kay): il seno dell’angolo fra la fibra e il vettore a metà fra luce e occhio, alla decima. Il tono viene da dove pende la fibra: lontano dalla lampada mostra il fianco illuminato, verso la lampada la punta scura, dritta lascia vedere il fondo del pelo. Sui bordi, dove il velluto si vede di taglio, una luce radente; ogni fibra è storta di un pelo diverso, pixel per pixel, e fa il luccichio del velluto.

La grana

Le righe fini lungo il pelo sono un rumore allungato lungo una di otto direzioni fisse, mescolando le due più vicine al verso del pelo. Il campo si legge con un piccolo spostamento di rumore, così i bordi della scia sono sfilacciati, e un rumore lento fa pendere il pelo un po’ diverso da un punto all’altro: il velluto vero non è mai uniforme.

L’onda e la scritta

Al clic GSAP allarga un anello dal punto premuto (dal centro con la tastiera e nell’anteprima) in WAVE secondi. Nello shader la cresta è un rilievo con una piccola increspatura dietro (un coseno sotto una campana) che piega la normale e getta le fibre in fuori; nello script, dietro la cresta, ogni cella viene pettinata nel verso COMB. Quando la cresta passa il centro la scritta cambia; DONE secondi dopo un’onda più morbida dal bordo destro rimette il velluto a riposo. Il pulsante è un button vero con aria-live e aria-busy, Invio e Spazio lo premono dal centro, l’anello del fuoco si vede solo con la tastiera. Senza WebGL resta un velluto dipinto coi gradienti del CSS.

Valori da cambiare

NomeFileDi partenzaCosa cambia
BRUSHscript.js11Quanto è larga la mano che spazzola il pelo, in pixel dal centro.
LAYscript.js0.85Quanto la mano stende il pelo: 0 niente, 1 piatto.
RELAXscript.js6I secondi che una scia ci mette a rialzarsi nel velluto.
NAPscript.js0.4Quanto pende in giù il pelo a riposo, com’è tessuto il velluto.
SHEENscript.js1Quanto è forte la lucentezza delle fibre.
GRAINscript.js1Quanta grana ha il tessuto: 0 liscio, 2 grosso.
COMBscript.js25Il verso in cui l’onda del clic pettina il pelo, in gradi: 0 verso destra, 90 verso il basso.
WAVEscript.js0.9I secondi che l’onda ci mette ad attraversare tutto il pulsante.
DONEscript.js2.2I secondi in cui il pulsante dice Added prima che il velluto venga lisciato com’era.

Provali nel Playground

Quando usarla

Per il pulsante principale della scheda prodotto di un negozio di moda, gioielli, profumi o arredamento, o di qualunque marchio che vende la sensazione di un materiale: un pulsante solo, su un fondo scuro e calmo, dove si ha voglia di toccarlo. Il colore del velluto si cambia nel CSS (verde bottiglia, blu notte, nero). Non per una griglia di prodotti con un pulsante per ognuno.

Sul telefono

Largo 320 pixel, o lo schermo meno 48, e alto 60. Il dito trascinato di traverso spazzola il pelo come il mouse premuto (touch-action: pan-y, così in su e in giù la pagina scorre ancora); se il dito si è spostato di più di 10 pixel non è un clic. Il tocco breve è il clic, con l’onda che parte da dove ha toccato il dito. La densità dei pixel è limitata a 2.

Con il movimento ridotto

Il velluto resta fermo: il puntatore non lascia scie, la pressione non affonda e non c’è la mano dell’arrivo. Al clic il velluto passa al tono pettinato in una dissolvenza di mezzo secondo, senza onda, e torna allo stesso modo; le scritte cambiano in dissolvenza, senza scivolare, e la spunta compare già disegnata.

Trappole

  • Le righe della grana prese in un sistema girato col pelo (il prodotto fra la posizione e la direzione) facevano, lontano dall’angolo in alto, dei ghirigori come le venature della radica: basta che la direzione cambi di pochissimo per spostare molto la fase. Ora il rumore è allungato lungo otto direzioni fisse, e si mescolano le due più vicine al pelo.
  • Con una campana gaussiana la scia aveva i bordi molli, più una macchia che il segno di una mano: una campana piatta la fa netta, e i bordi sfilacciati li fa il campo letto con un piccolo spostamento di rumore.
  • Se il pelo si rialza subito, con la sola esponenziale, la scia sbiadisce mentre la si guarda e non sembra velluto: ogni cella spazzolata tiene il segno per un terzo di RELAX e poi lo lascia andare.
  • Un campo che si rilassa da solo sulla GPU, in una texture a 8 bit, si ferma a metà: verso la fine i passi di un fotogramma sono più piccoli di un 255esimo e si arrotondano a zero. Il campo vive nello script in Float32Array, e la texture serve solo a disegnarlo.
  • Pettinato al massimo il velluto diventava rosa caramella, un peluche: il pettine lo stende a 0,56 e la lucentezza resta bassa, così Added è ancora bordeaux con un riflesso.
  • Un dito trascinato per spazzolare finiva con un clic e metteva la borsa nel carrello: si conta la strada fatta premendo, e oltre 10 pixel il clic non vale.

Librerie

GSAP 3.15.0, Bodoni Moda (font variabile) 5.3.0.

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

Collaudo

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