Vai al contenuto
animorio
EN
Tutti i componenti

Il pulsante del razzo

Pulsanti, Fisica, Transizioni, SVGCanvas, GSAPImpegnativaPeso compresso: Demo 13 KBGSAP 28 KBGratisScarica lo zip

Il pulsante che manda una campagna: un conto alla rovescia 3, 2, 1 sul rullo delle cifre, il razzo che vibra nel suo pozzetto, l'accensione con le scintille e il fumo che esce da sotto la pillola, poi il decollo con un pennacchio che si arriccia nell'aria finché il razzo sparisce in alto. Resta Launched con un filo di fumo, e un razzo nuovo risale dal pozzetto.

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 rocket launch button</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/geist@5.3.0/index.css">
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <!-- the smoke under the button: the exhaust pours out from under the pill as from a launch pad, and the plume -->
  <canvas class="sky sky--back" data-sky="back" aria-hidden="true"></canvas>

  <main class="stage">
    <!-- the launch button: a countdown on a rolling digit, the rocket shakes on its pad, lifts off with a plume of
         smoke and flies out of the page; the button stays Launched with a thin wisp of smoke, then a new rocket rises -->
    <div class="launch" data-launch data-autoclic>
      <button class="launch__btn" type="button" aria-label="Launch campaign to 12,480 subscribers" data-btn>
        <span class="launch__heat" data-heat aria-hidden="true"></span>
        <span class="launch__pad" data-pad aria-hidden="true">
          <svg class="launch__ring" viewBox="0 0 64 64"><circle cx="32" cy="32" r="30" pathLength="1" data-ring/></svg>
        </span>
        <span class="launch__label" aria-hidden="true">
          <span class="launch__line" data-line="idle">Launch campaign</span>
          <span class="launch__line" data-line="count">Launching in<span class="launch__digits"><span class="launch__reel" data-reel></span></span></span>
          <span class="launch__line launch__line--done" data-line="done"><svg class="launch__check" viewBox="0 0 24 24"><path d="M5 12.6l4.3 4.3L19 7.2" pathLength="1" data-check/></svg>Launched</span>
        </span>
      </button>
      <p class="launch__hint"><span data-hint>12,480 subscribers, sent all at once</span></p>
      <p class="sr" aria-live="polite" data-live></p>
    </div>
  </main>

  <!-- the smoke over the button: the vapour before ignition, the puffs at the rim of the well, the thin wisp -->
  <canvas class="sky" data-sky="front" aria-hidden="true"></canvas>

  <!-- the rocket: it sits over the pad, and the clip lets a new one rise out of the pad as from a silo -->
  <svg class="rocket" data-rocket viewBox="-40 -60 80 120" aria-hidden="true">
    <defs>
      <linearGradient id="rk-hull" x1="0" y1="0" x2="1" y2="0">
        <stop offset="0" class="rocket__hull-a"/>
        <stop offset="0.38" class="rocket__hull-b"/>
        <stop offset="0.72" class="rocket__hull-c"/>
        <stop offset="1" class="rocket__hull-d"/>
      </linearGradient>
      <linearGradient id="rk-fin" x1="0" y1="0" x2="1" y2="0">
        <stop offset="0" class="rocket__fin-a"/>
        <stop offset="1" class="rocket__fin-b"/>
      </linearGradient>
      <linearGradient id="rk-metal" x1="0" y1="0" x2="1" y2="0">
        <stop offset="0" stop-color="#5b6070"/>
        <stop offset="0.45" stop-color="#b9bdc8"/>
        <stop offset="1" stop-color="#3d414d"/>
      </linearGradient>
      <linearGradient id="rk-heat" x1="0" y1="0" x2="0" y2="1">
        <stop offset="0.35" class="rocket__heat-a"/>
        <stop offset="1" class="rocket__heat-b"/>
      </linearGradient>
      <radialGradient id="rk-glow">
        <stop offset="0" class="rocket__glow-a"/>
        <stop offset="0.35" class="rocket__glow-m"/>
        <stop offset="1" class="rocket__glow-b"/>
      </radialGradient>
      <linearGradient id="rk-flame" x1="0" y1="0" x2="0" y2="1" gradientUnits="objectBoundingBox">
        <stop offset="0" class="rocket__flame-a"/>
        <stop offset="0.3" class="rocket__flame-b"/>
        <stop offset="1" class="rocket__flame-c"/>
      </linearGradient>
      <linearGradient id="rk-core" x1="0" y1="0" x2="0" y2="1" gradientUnits="objectBoundingBox">
        <stop offset="0" stop-color="#fff"/>
        <stop offset="0.5" class="rocket__core-a"/>
        <stop offset="1" class="rocket__core-b"/>
      </linearGradient>
      <clipPath id="rk-body"><path d="M0 -27C7.4 -21 10.2 -10 10.2 3.5L9.2 15.2Q9 17.4 6.9 17.4H-6.9Q-9 17.4 -9.2 15.2L-10.2 3.5C-10.2 -10 -7.4 -21 0 -27Z"/></clipPath>
      <clipPath id="rk-silo" clipPathUnits="userSpaceOnUse"><path data-silo d="M-600 -6000H600V0H26A26 26 0 0 1 -26 0H-600Z"/></clipPath>
    </defs>
    <!-- the light of the flame round the rocket, and where the flame hits the floor of the well -->
    <circle class="rocket__halo" r="1" data-halo/>
    <ellipse class="rocket__splash" cx="0" cy="25" rx="40" ry="8" data-splash/>
    <g clip-path="url(#rk-silo)">
      <g data-craft>
        <!-- the flame, redrawn every frame under the nozzle: the outer flame, the white core, the bright knots -->
        <g class="rocket__flame" data-flame>
          <path class="rocket__fire" data-fire/>
          <path class="rocket__core" data-core/>
          <path class="rocket__knots" data-knots/>
        </g>
        <path class="rocket__fin" d="M-9.4 1.5C-14.8 5.6 -17.6 11.6 -17.4 20.6L-9 15.6Z"/>
        <path class="rocket__fin" d="M9.4 1.5C14.8 5.6 17.6 11.6 17.4 20.6L9 15.6Z"/>
        <path class="rocket__nozzle" d="M-5.2 17.2H5.2L6.8 23.4Q6.9 24.2 6.1 24.2H-6.1Q-6.9 24.2 -6.8 23.4Z"/>
        <path class="rocket__hull" d="M0 -27C7.4 -21 10.2 -10 10.2 3.5L9.2 15.2Q9 17.4 6.9 17.4H-6.9Q-9 17.4 -9.2 15.2L-10.2 3.5C-10.2 -10 -7.4 -21 0 -27Z"/>
        <g clip-path="url(#rk-body)">
          <rect class="rocket__cap" x="-12" y="-30" width="24" height="15.5"/>
          <rect class="rocket__band" x="-12" y="8.2" width="24" height="2"/>
          <rect class="rocket__burn" x="-12" y="-4" width="24" height="24" data-burn/>
        </g>
        <path class="rocket__keel" d="M-1.3 9.5H1.3V22.2Q1.3 23.4 0 23.4Q-1.3 23.4 -1.3 22.2Z"/>
        <circle class="rocket__rim" cx="0" cy="-4" r="5.2"/>
        <circle class="rocket__glass" cx="0" cy="-4" r="3.6"/>
        <path class="rocket__shine" d="M-2.2 -5.6A2.6 2.6 0 0 1 0.2 -6.9"/>
      </g>
    </g>
    <!-- the sparks of the ignition: short streaks, all in one path -->
    <path class="rocket__sparks" data-sparks/>
  </svg>

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

23 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 del razzo» da Animorio e adattala al mio sito

Cosa fa

Su un fondo nero un pulsante a pillola color grafite: a sinistra un pozzetto tondo con dentro un piccolo razzo bianco e corallo, a destra la scritta Launch campaign; sotto, allineata alla scritta e quindi a destra del pozzetto, la riga 12,480 subscribers, sent all at once. Col mouse sopra il razzo si solleva un poco e sotto di lui sfarfalla una fiammella. Cliccando, la scritta sale via e arriva Launching in 3, mentre la riga sotto dice Press again to abort; il 3 rotola in 2 e poi in 1 come le cifre di un contatore, intorno al pozzetto un anello corallo si riempie, il pozzetto dà un piccolo colpo a ogni numero e il razzo trema sempre di più; sull'1 sbuffa un po' di vapore dai lati. A zero si accende e la riga dice Sending to 12,480 inboxes: una fiamma bianca e arancio esce dall'ugello, schizzano scintille che ricadono, il pulsante si scalda di luce arancio e trema, e il fumo dello scarico esce da sotto la pillola ai due lati, caldo vicino alla fiamma. Dopo un attimo il razzo si stacca e sale sempre più in fretta inclinandosi un poco, con la fiamma lunga e i nodi luminosi dello scarico, lasciando un pennacchio che si gonfia e si arriccia nell'aria; sparisce in alto mentre la scritta diventa una spunta con Launched e la riga sotto dice Sent to 12,480 inboxes. Dal pozzetto vuoto sale un filo di fumo. Dopo un momento, o con un clic, un razzo nuovo risale dal fondo del pozzetto e il pulsante torna Launch campaign. Cliccando durante il conto alla rovescia il lancio si annulla e la riga dice Launch aborted.

Come funziona

Il conto alla rovescia sul rullo

Le cifre da COUNT a 1 stanno in colonna dentro una finestra alta una cifra: a ogni battuta (BEAT secondi) la colonna sale di una cifra con expo.out, come un contatore meccanico. Nello stesso tempo un cerchio SVG con pathLength 1 si riempie con stroke-dashoffset da 1 a 0, e un numero shake che GSAP fa crescere con power1.in decide quanto trema il razzo.

Il razzo sopra al pozzetto

Il razzo è un SVG fisso sulla pagina, fuori dal pulsante, così può volare via: a ogni fotogramma si mette sopra al pozzetto leggendo getBoundingClientRect, e segue il pulsante quando si stringe, trema o la finestra cambia misura. Il tremito è rumore simplex letto a velocità alta, l'inclinazione cresce col quadrato della salita, e un clipPath a forma di pozzetto lascia risalire dal fondo il razzo nuovo come da un silo.

La fiamma ridisegnata

La fiamma è disegnata nel sistema del razzo, sotto l'ugello: due curve di Bézier che si incontrano in punta, una fuori arancio e una dentro bianca. La lunghezza segue la spinta (da fiammella a pieno regime) e sfarfalla con due rumori a frequenze diverse; sulla piattaforma è tagliata al fondo del pozzetto e lì si allarga in una luce schiacciata. A pieno regime compaiono i nodi luminosi dello scarico.

Il fumo a particelle

Ogni sbuffo è una particella su una tela grande quanto la pagina: è spinto dal rotore di un campo di rumore che scorre nel tempo (la derivata del rumore girata di 90 gradi), così il fumo gira su sé stesso senza mai ammucchiarsi; sale un poco, è frenato dall'aria, cresce e svanisce invecchiando. Sulla piattaforma lo scarico va giù, tocca il pavimento sotto il pulsante e si allarga ai due lati; in volo il razzo lascia uno sbuffo ogni sette pixel di strada.

Due tele, sotto e sopra

Il fumo sta su due tele: quella sotto il pulsante prende lo scarico e il primo tratto del pennacchio, che così esce da sotto la pillola senza coprire la scritta; quella sopra prende il vapore, gli sbuffi sull'orlo del pozzetto e il filo di fumo finale. Gli sbuffi sono quattro disegni pronti di nuvolette sovrapposte, in due versioni, grigia e scaldata dalla fiamma, e la tela va a mezza risoluzione: il fumo è morbido, e così la scheda grafica lavora un quarto.

Valori da cambiare

NomeFileDi partenzaCosa cambia
COUNTscript.js3Il numero da cui parte il conto alla rovescia.
BEATscript.js0.8I secondi di ogni numero del conto alla rovescia.
SHAKEscript.js1Quanto trema il razzo sulla piattaforma prima di partire.
FLIGHTscript.js1.5I secondi che il razzo impiega a uscire dalla pagina.
LEANscript.js9Di quanti gradi si inclina a destra il razzo salendo.
SMOKEscript.js1Quanto fumo: 0,5 è metà degli sbuffi, 2 il doppio.
SWIRLscript.js1Quanto il fumo si arriccia e gira salendo.
DONEscript.js2.6I secondi in cui il pulsante dice Launched prima che risalga un razzo nuovo.

Provali nel Playground

Quando usarla

Per l'azione grossa di un'app, quella che parte e non torna indietro: mandare una campagna o una newsletter, pubblicare un sito, mettere in produzione, lanciare un prodotto. Il conto alla rovescia lascia il tempo di ripensarci e annullare. Vuole una pagina scura e spazio sopra il pulsante, dove il razzo vola.

Sul telefono

Il pulsante è largo 340 pixel, o lo schermo meno 48; il razzo si rimette sopra al pozzetto a ogni fotogramma, quindi segue anche il giro dello schermo. Il tocco fa il conto alla rovescia come il clic; la fiammella del passaggio del mouse al tocco non c'è. Le tele del fumo vanno a mezza risoluzione anche sugli schermi densi.

Con il movimento ridotto

Il conto alla rovescia resta, con le cifre che cambiano senza rotolare e l'anello che si riempie; il razzo non trema e non vola: a zero svanisce dal pozzetto e compare Launched con la spunta. Niente fumo, fiamma o scintille. Al ritorno il razzo ricompare con una dissolvenza.

Trappole

  • Con la prima versione (fumo a piena risoluzione, mescolato in modo additivo con 'lighter', e la luce della fiamma come seconda passata) un browser senza scheda grafica restava bloccato per decine di secondi: ora la tela va a mezza risoluzione con la mescolanza normale, il calore è una seconda serie di sbuffi già colorati e la fiamma è un tracciato SVG.
  • GSAP arrotonda ai pixel i valori in px: lo stroke-dashoffset da 1 a 0 dell'anello saltava a metà invece di riempirsi. Serve autoRound: false.
  • Una tela sola sopra tutto copriva la scritta col fumo dello scarico: le tele sono due, e lo scarico va su quella sotto il pulsante, da cui esce ai lati come da una vera piattaforma.
  • Il razzo non può stare dentro il pulsante, o non potrebbe uscirne: è un elemento fisso della pagina rimesso sopra al pozzetto a ogni fotogramma, così segue anche la pressione, il tremito e il cambio di misura.
  • La tela non legge le variabili CSS: i colori del fumo e della fiamma si leggono con getComputedStyle e si ridisegnano negli sbuffi a ogni lancio, così cambiarli dal vivo funziona.
  • Il passo di tempo delle particelle è limitato a 1/30 di secondo: dopo una scheda rimasta in secondo piano, un salto di tempo le sparerebbe via tutte insieme.

Librerie

GSAP 3.15.0, Geist (font variabile) 5.3.0.

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

Collaudo

Provata il 4 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.

Tutti i componenti