
L’indicatore a lancetta
Contatori, Fisica, SVG
NuovaGratis
Nello stile ricco, colorato e pieno di cose: il modulo contatti di una serra, Fernhouse. A sinistra un angolo di serra con i vetri a riquadri, la luce che entra, il davanzale con due vasetti e un filodendro in un grande vaso di terracotta; a destra i campi, cartellini di legno da vaso. Mentre scrivi spunta un germoglio arrotolato dal nodo dello stelo; quando il cartellino è giusto il picciolo si allunga e la foglia si srotola e si apre su una molla; se è sbagliato la foglia ingiallisce, si affloscia e cade dal nodo lasciando una cicatrice. Inviato, il messaggio viene chiuso in un pacchetto di semi illustrato che vola nel vaso, un innaffiatoio lo bagna e il bocciolo si apre petalo per petalo.
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 greenhouse contact form</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/bricolage-grotesque@5.3.0/index.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/caveat@5.3.0/index.css">
<link rel="stylesheet" href="style.css">
</head>
<body>
<main class="stage">
<!-- the contact form of a greenhouse: every field is a wooden plant label, and the philodendron in the pot beside
it pushes a sprout while you write, unrolls a leaf when the label is right, lets it wilt and drop when it is
wrong; sent, the message is sealed in a seed packet, planted in the pot and watered until the plant blooms -->
<section class="serra" aria-labelledby="serra-title" data-serra data-autoclic>
<div class="serra__scene" aria-hidden="true">
<svg class="scene" viewBox="0 0 300 360" data-svg>
<defs>
<linearGradient id="serra-glass" x1="0" y1="0" x2="0.4" y2="1">
<stop offset="0" class="stop-glass-top"/>
<stop offset="1" class="stop-glass"/>
</linearGradient>
<linearGradient id="serra-leaf" x1="0" y1="0" x2="0" y2="1">
<stop offset="0" class="stop-leaf-light"/>
<stop offset="1" class="stop-leaf"/>
</linearGradient>
<linearGradient id="serra-dry" x1="0" y1="0" x2="0" y2="1">
<stop offset="0" class="stop-dry-light"/>
<stop offset="1" class="stop-dry"/>
</linearGradient>
<linearGradient id="serra-clay" x1="0" y1="0" x2="1" y2="0">
<stop offset="0" class="stop-clay-dark"/>
<stop offset="0.3" class="stop-clay-light"/>
<stop offset="0.62" class="stop-clay"/>
<stop offset="1" class="stop-clay-dark"/>
</linearGradient>
<linearGradient id="serra-can" x1="0" y1="0" x2="1" y2="0">
<stop offset="0" class="stop-can-dark"/>
<stop offset="0.35" class="stop-can-light"/>
<stop offset="1" class="stop-can"/>
</linearGradient>
<linearGradient id="serra-wood" x1="0" y1="0" x2="0" y2="1">
<stop offset="0" class="stop-wood-light"/>
<stop offset="1" class="stop-wood"/>
</linearGradient>
<clipPath id="serra-room">
<rect x="0" y="0" width="300" height="360" rx="18"/>
</clipPath>
</defs>
<g clip-path="url(#serra-room)">
<!-- the greenhouse: glass panes in a green iron frame, the garden outside, light coming in -->
<rect x="0" y="0" width="300" height="360" fill="url(#serra-glass)"/>
<g class="outside">
<path d="M-10 300 C 20 250, 40 262, 62 236 C 80 214, 104 240, 120 228 C 146 206, 170 236, 196 222 C 224 206, 250 232, 272 214 C 292 200, 310 218, 320 214 V 330 H -10 Z" class="outside__far"/>
<path d="M-10 312 C 16 282, 44 296, 70 276 C 96 258, 120 288, 150 276 C 182 262, 210 290, 240 272 C 266 258, 292 280, 320 268 V 330 H -10 Z" class="outside__near"/>
<path d="M34 278 C 30 250, 18 236, 6 232 M34 278 C 40 254, 54 242, 64 240 M34 278 C 34 246, 36 226, 32 210" class="outside__fern"/>
<path d="M262 270 C 258 246, 246 232, 236 230 M262 270 C 268 248, 280 238, 292 236" class="outside__fern"/>
</g>
<g class="beams" data-beams>
<path d="M70 -10 L 120 -10 L 240 360 L 150 360 Z"/>
<path d="M150 -10 L 176 -10 L 300 300 L 262 330 Z"/>
<path d="M10 -10 L 34 -10 L 120 360 L 80 360 Z"/>
</g>
<g class="panes">
<path d="M8 120 L 140 120 M160 120 L 292 120 M8 236 L 292 236" class="frame__rail"/>
<path d="M6 0 V 330 M150 0 V 330 M294 0 V 330 M78 0 V 330 M222 0 V 330" class="frame__bar"/>
<path d="M10 112 L 70 20 M84 112 L 144 20 M156 112 L 216 20 M228 112 L 288 20 M18 228 L 70 140 M162 228 L 214 140" class="glass__shine"/>
</g>
<g class="mist" data-mist></g>
<!-- the sill the pots stand on -->
<rect x="-4" y="330" width="308" height="34" class="sill"/>
<rect x="-4" y="326" width="308" height="8" rx="2" class="sill__top"/>
<path d="M-4 334 H 304" class="sill__edge"/>
<!-- two little pots further along the sill: an echeveria and a cactus -->
<g transform="translate(38 326)">
<path d="M-16 -18 H 16 L 12 0 H -12 Z" fill="url(#serra-clay)"/>
<rect x="-18" y="-22" width="36" height="6" rx="2" class="pot__rim-small"/>
<g class="succulent">
<path d="M0 -22 C -10 -26, -16 -34, -12 -40 C -6 -34, -2 -30, 0 -22 Z"/>
<path d="M0 -22 C 10 -26, 16 -34, 12 -40 C 6 -34, 2 -30, 0 -22 Z"/>
<path d="M0 -22 C -6 -30, -6 -40, 0 -46 C 6 -40, 6 -30, 0 -22 Z"/>
<path d="M0 -22 C -14 -22, -22 -26, -22 -30 C -14 -30, -6 -27, 0 -22 Z" class="succulent__back"/>
<path d="M0 -22 C 14 -22, 22 -26, 22 -30 C 14 -30, 6 -27, 0 -22 Z" class="succulent__back"/>
</g>
</g>
<g transform="translate(266 326)">
<path d="M-13 -16 H 13 L 10 0 H -10 Z" fill="url(#serra-clay)"/>
<rect x="-15" y="-20" width="30" height="5" rx="2" class="pot__rim-small"/>
<path d="M-6 -20 V -44 C -6 -52, 6 -52, 6 -44 V -20 Z" class="cactus"/>
<path d="M6 -32 H 11 V -40 C 11 -45, 16 -45, 16 -40 V -30 C 16 -27, 14 -26, 11 -26 H 6 Z" class="cactus"/>
<path d="M-2 -46 V -22 M2 -46 V -22" class="cactus__rib"/>
<circle cx="0" cy="-50" r="3" class="cactus__flower"/>
</g>
<!-- the big pot: saucer, terracotta with the marks of the wheel, soil with pebbles and moss -->
<ellipse cx="150" cy="331" rx="66" ry="5" class="pot__shadow"/>
<path d="M88 322 H 212 L 206 330 H 94 Z" class="pot__saucer"/>
<g data-pot>
<path d="M96 276 H 204 L 194 326 H 106 Z" fill="url(#serra-clay)"/>
<path d="M98 288 H 202 M100 300 H 200 M102 312 H 198" class="pot__wheel"/>
<path d="M96 276 H 204 L 203 282 H 97 Z" class="pot__under-rim"/>
<rect x="88" y="260" width="124" height="18" rx="4" fill="url(#serra-clay)"/>
<path d="M90 263 H 210" class="pot__rim-light"/>
</g>
<ellipse cx="150" cy="261" rx="58" ry="6" class="soil"/>
<ellipse cx="150" cy="261" rx="58" ry="6" class="soil__wet" data-wet/>
<g class="soil__bits">
<ellipse cx="112" cy="261" rx="3" ry="1.6"/>
<ellipse cx="126" cy="263" rx="2" ry="1.2"/>
<ellipse cx="176" cy="260" rx="2.6" ry="1.4"/>
<ellipse cx="190" cy="262" rx="1.8" ry="1"/>
</g>
<path d="M100 262 C 106 256, 116 257, 120 261 C 116 264, 104 265, 100 262 Z M178 262 C 184 257, 196 258, 200 261 C 194 264, 182 265, 178 262 Z" class="moss"/>
<!-- the plant, drawn by the script: stem, leaves on their petioles, the flower bud on top -->
<g data-plant>
<path d="M150 262 C 142 222, 160 196, 151 162 S 144 110, 152 74" class="stem" data-stem/>
<path d="M150 262 C 142 222, 160 196, 151 162 S 144 110, 152 74" class="stem__light"/>
<g data-scars></g>
<g data-leaves></g>
<g data-flower></g>
</g>
<!-- the seed packet once planted: a little packet on a stick in the soil -->
<g transform="translate(184 262)">
<g class="marker" data-marker>
<path d="M0 4 V -28" class="marker__stick"/>
<rect x="-11" y="-50" width="22" height="26" rx="2" class="marker__paper"/>
<path d="M-11 -46 L -7 -50 L -3 -46 L 1 -50 L 5 -46 L 9 -50 L 11 -48 V -44 H -11 Z" class="marker__band"/>
<path d="M0 -28 C -2 -34, -6 -36, -8 -36 C -8 -32, -4 -30, 0 -30 Z M0 -30 C 2 -36, 6 -38, 8 -38 C 8 -34, 4 -32, 0 -32 Z" class="marker__leaf"/>
</g>
</g>
<!-- the watering can and its water, out of the way until the message is sent -->
<g data-water></g>
<g class="can" data-can>
<g data-can-tilt>
<path d="M-4 -32 C -4 -58, 54 -58, 54 -32" class="can__handle"/>
<path d="M-8 -20 L -62 -60" class="can__spout-back"/>
<path d="M-8 -20 L -62 -60" class="can__spout"/>
<g transform="translate(-64 -62) rotate(-38)">
<path d="M-3 -9 L 6 -6 V 6 L -3 9 Z" class="can__rose"/>
<path d="M-3 -9 C -7 -5, -7 5, -3 9" class="can__rose-face"/>
</g>
<path d="M-10 -34 H 60 V 14 C 60 22, -10 22, -10 14 Z" fill="url(#serra-can)"/>
<path d="M-10 -34 C -10 -40, 60 -40, 60 -34 C 60 -28, -10 -28, -10 -34 Z" class="can__top"/>
<path d="M-10 -8 H 60" class="can__band"/>
<path d="M2 -26 V 10" class="can__shine"/>
</g>
</g>
</g>
<rect x="0.5" y="0.5" width="299" height="359" rx="17.5" class="scene__edge"/>
</svg>
</div>
<div class="serra__side">
<form class="serra__form" action="#" novalidate data-form>
<h2 class="serra__title" id="serra-title">Write to the greenhouse</h2>
<div class="tag" data-field="name">
<label class="tag__label" for="serra-name">Your name</label>
<input class="tag__input" id="serra-name" name="name" type="text" autocomplete="name" spellcheck="false" aria-describedby="serra-err-name" data-input>
<span class="tag__err" id="serra-err-name" data-err></span>
<span class="tag__hole" aria-hidden="true"></span>
</div>
<div class="tag" data-field="email">
<label class="tag__label" for="serra-email">Email</label>
<input class="tag__input" id="serra-email" name="email" type="email" autocomplete="email" spellcheck="false" inputmode="email" aria-describedby="serra-err-email" data-input>
<span class="tag__err" id="serra-err-email" data-err></span>
<span class="tag__hole" aria-hidden="true"></span>
</div>
<div class="tag tag--long" data-field="message">
<label class="tag__label" for="serra-message">What is growing on your mind?</label>
<textarea class="tag__input" id="serra-message" name="message" rows="2" aria-describedby="serra-err-message" data-input></textarea>
<span class="tag__err" id="serra-err-message" data-err></span>
<span class="tag__hole" aria-hidden="true"></span>
</div>
<div class="serra__foot">
<button class="send" type="submit" data-send>
<svg class="send__sprout" viewBox="0 0 20 20" aria-hidden="true">
<path d="M10 18 V9"/>
<path d="M10 11 C 10 6, 6 4, 2 5 C 2 9, 6 11, 10 11 Z"/>
<path d="M10 9 C 10 5, 14 3, 18 4 C 18 8, 14 10, 10 9 Z"/>
</svg>
<span class="send__word" data-word>Plant message</span>
</button>
</div>
</form>
<!-- the seed packet the message is sealed in -->
<div class="packet" data-packet aria-hidden="true">
<div class="packet__body" data-packet-body>
<div class="packet__flap" data-flap>
<span class="packet__flap-back"></span>
</div>
<div class="packet__paper">
<div class="packet__head">
<span class="packet__brand">Fernhouse</span>
<span class="packet__kind">Seeds</span>
</div>
<svg class="packet__art" viewBox="0 0 120 70">
<rect x="0" y="0" width="120" height="70" rx="4" class="art__sky"/>
<circle cx="94" cy="20" r="11" class="art__sun"/>
<path d="M0 58 C 30 50, 60 62, 120 52 V 70 H 0 Z" class="art__ground"/>
<path d="M46 62 C 44 46, 50 34, 48 18" class="art__stem"/>
<path d="M47 48 C 30 46, 20 36, 18 28 C 30 28, 42 34, 47 48 Z" class="art__leaf"/>
<path d="M48 36 C 62 32, 70 22, 70 14 C 60 16, 50 24, 48 36 Z" class="art__leaf"/>
<g transform="translate(48 16)" class="art__bloom">
<ellipse cx="0" cy="-6" rx="4" ry="6"/>
<ellipse cx="0" cy="-6" rx="4" ry="6" transform="rotate(72)"/>
<ellipse cx="0" cy="-6" rx="4" ry="6" transform="rotate(144)"/>
<ellipse cx="0" cy="-6" rx="4" ry="6" transform="rotate(216)"/>
<ellipse cx="0" cy="-6" rx="4" ry="6" transform="rotate(288)"/>
<circle r="3.4" class="art__heart"/>
</g>
</svg>
<p class="packet__variety">Variety: <span data-note-name></span></p>
<p class="packet__note" data-note></p>
<div class="packet__foot">
<span class="packet__window" data-seeds>
<i></i><i></i><i></i><i></i><i></i><i></i>
</span>
<span class="packet__sow">Sow today, blooms in two days</span>
</div>
</div>
</div>
</div>
<!-- what stays once the packet is in the soil -->
<div class="done" data-done>
<p class="done__title">Message planted</p>
<p class="done__text">It is in the pot by the window. We water every message within two days.</p>
<button class="again" type="button" data-again>Write another</button>
</div>
</div>
<p class="sr" aria-live="polite" data-live></p>
</section>
</main>
<script src="https://cdn.jsdelivr.net/npm/gsap@3.15.0/dist/gsap.min.js"></script>
<script src="script.js"></script>
</body>
</html>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.
41 valori da cambiare
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 modulo contatti della serra» da Animorio e adattala al mio sitoVetri, telaio, giardino, fasci di luce, davanzale, i due vasetti e il vaso grande sono tracciati fissi in un SVG di 300 per 360; le sfumature hanno gli stop con una classe e il colore nel CSS, così la Palette del Playground li ricolora. La condensa sono ventisei goccioline create dallo script.
Ogni foglia è un gruppo sul suo nodo dello stelo (punto preso con getPointAtLength, specchiato per il lato sinistro) e ha pochi numeri: cresciuta, afflosciata, gialla, caduta, e il vento su di lei. A ogni tick di GSAP lo script calcola l’angolo e la lunghezza del picciolo, lo disegna come una curva dal nodo alla punta e mette la lamina esattamente sulla punta, ruotata e scalata: mentre è un germoglio è piccola, rivolta in alto e arrotolata (scala verticale 0,14), aprendosi si srotola fino a 1. Così la foglia non si stacca mai dal suo picciolo, qualunque cosa faccia.
La pianta ondeggia sul vaso e ogni foglia trema su due molle smorzate integrate nel ticker (SPRING regola rigidità e smorzamento): quando una foglia si apre la pianta riceve una spinta e le altre foglie una più piccola; mentre l’acqua cade, ogni tanto una goccia ne tocca una.
A ogni input il campo viene controllato (nome di almeno due lettere, email con chiocciola e fine come .com, messaggio di almeno dieci lettere): se è ancora sbagliato il germoglio cresce un poco con le lettere, se è giusto la foglia si apre in GROW secondi con elastic.out. Lasciando un campo sbagliato la foglia diventa gialla, si affloscia di DROOP gradi con bounce.out e poi cade: tutta l’unità, picciolo compreso, scende al davanzale ruotando e svanisce, e sul nodo compare la cicatrice. Il campo prende aria-invalid e il testo d’errore legato con aria-describedby.
Una timeline ripiega i cartellini, fa salire il pacchetto di semi (HTML con il disegno in SVG), chiude l’aletta con rotationX in una prospettiva CSS e fa ballare i semi; poi misura dove sta il bastoncino nel vaso e ci fa volare il pacchetto, che lì diventa quello piccolo in SVG. L’innaffiatoio entra e si inclina: dalla rosa, calcolata dalla sua rotazione, partono sette filetti (curve quadratiche col tratteggio che scorre) e DROPS gocce lungo le stesse curve, con gli schizzi sul terriccio, per RAIN secondi; il terriccio si scurisce, le foglie si alzano e i sei petali si aprono uno dopo l’altro con back.out.
| Nome | File | Di partenza | Cosa cambia |
|---|---|---|---|
GROW | script.js | 1.2 | Quanti secondi ci mette una foglia a srotolarsi e aprirsi. |
SPRING | script.js | 0.38 | Quanto sono elastiche la pianta e le foglie: più basso, più ondeggiano. |
DROOP | script.js | 70 | Di quanti gradi si affloscia una foglia assetata prima di cadere. |
SWAY | script.js | 5 | Di quanti gradi ondeggia la pianta quando si apre una foglia. |
RAIN | script.js | 1.8 | Quanti secondi versa l’innaffiatoio. |
DROPS | script.js | 28 | Quante gocce ci sono in aria mentre versa. |
WAIT | script.js | 0.5 | Quanti secondi dura l’invio finto. |
TYPE_SPEED | script.js | 0.07 | Secondi per lettera quando l’anteprima scrive da sola. |
Per la pagina dei contatti di un vivaio, di un fiorista, di un orto, di un paesaggista o di qualsiasi sito che parla di piante: il modulo diventa la parte che si ricorda.
La scheda resta su due colonne a metà, la serra e i campi: la pianta, le foglie, il pacchetto e l’innaffiatoio sono gli stessi; il testo d’errore va sotto il campo, il disegno sul pacchetto si toglie e i caratteri si stringono, così tutto sta in una casella di 341 per 410.
Con il movimento ridotto le foglie cambiano posa di colpo e compaiono in dissolvenza, senza molle né ondeggiare; la foglia sbagliata ingiallisce e svanisce invece di cadere. Inviato, il pacchetto compare già chiuso e svanisce, niente volo né innaffiatoio: il terriccio si scurisce e il fiore compare aperto in dissolvenza.
GSAP 3.15.0, Bricolage Grotesque (font variabile) 5.3.0, Caveat (font variabile) 5.3.0.
Compressi con gzip, i tre file della demo pesano 17 KB; le librerie: GSAP 28 KB.
Provata il 22 ottobre 2026
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.
Con l’email e la password del tuo account.
oppure con l’email
Hai fatto l’accesso come .
Con l’account scarichi lo zip di ogni animazione e di ogni pacchetto, gratis.