
Il banner dei cookie
Consenso, Transizioni, SVG, Fisica
NuovaGratis
Un menu come una linea della metropolitana: le voci sono le fermate, e scegliendone una un vagoncino ci va seguendo il tracciato, rallentando nelle curve e ondeggiando, mentre la linea si colora dietro di lui; da una fermata di scambio una diramazione porta alle sottovoci.
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 metro map menu</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/overpass@5.3.0/index.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/doto@5.3.0/index.css">
<link rel="stylesheet" href="style.css">
</head>
<body>
<main class="stage">
<div class="layout" data-layout>
<!-- the menu: a metro line. The stops are links laid over the drawing; a little car rides the line to the stop
chosen, and the line takes its colour behind it. Venues is an interchange: a branch leads to its halls -->
<nav class="map" aria-label="Main" data-map>
<svg class="map__art" viewBox="0 0 360 540" aria-hidden="true" data-art>
<defs>
<radialGradient id="beam" cx="0" cy="0.5" r="1" fx="0" fy="0.5">
<stop offset="0" stop-color="#fff3c4" stop-opacity="0.95" />
<stop offset="1" stop-color="#fff3c4" stop-opacity="0" />
</radialGradient>
</defs>
<g data-tracks></g>
<g data-ghost></g>
<g data-paint></g>
<path class="route" data-route />
<g data-marks></g>
<!-- the car, seen from above: the end with the white lamps is the one it travels towards -->
<!-- the shadow: three soft layers instead of a blur filter, which would be redrawn at every frame -->
<g class="car__shadow" data-shadow>
<rect x="-23" y="-10.5" width="46" height="21" rx="10" />
<rect x="-21.5" y="-9" width="43" height="18" rx="8.5" />
<rect x="-20" y="-7.5" width="40" height="15" rx="7" />
</g>
<g class="car" data-car>
<g data-body>
<ellipse class="car__beam" cx="34" cy="0" rx="16" ry="8" fill="url(#beam)" data-beam />
<rect class="car__body" x="-20" y="-7.5" width="40" height="15" rx="7" />
<rect class="car__roof" x="-12.5" y="-4.6" width="25" height="9.2" rx="2.4" />
<rect class="car__stripe" x="-12.5" y="-1.5" width="25" height="3" rx="1.5" />
<path class="car__glass" d="M14 -5.4h1.6a3.6 3.6 0 0 1 3.4 3.4v4a3.6 3.6 0 0 1-3.4 3.4H14z" />
<path class="car__glass" d="M-14 -5.4h-1.6a3.6 3.6 0 0 0-3.4 3.4v4a3.6 3.6 0 0 0 3.4 3.4H-14z" />
<circle class="car__lamp car__lamp--a" cx="18.6" cy="-5" r="1.25" />
<circle class="car__lamp car__lamp--a" cx="18.6" cy="5" r="1.25" />
<circle class="car__lamp car__lamp--b" cx="-18.6" cy="-5" r="1.25" />
<circle class="car__lamp car__lamp--b" cx="-18.6" cy="5" r="1.25" />
</g>
</g>
</svg>
<ol class="map__stops">
<li><a class="stop" href="#" data-stop="welcome" aria-current="page">Welcome</a></li>
<li><a class="stop" href="#" data-stop="programme">Programme</a></li>
<li><a class="stop" href="#" data-stop="tours">Tours</a></li>
<li>
<a class="stop stop--change" href="#" data-stop="venues">Venues</a>
<ol class="map__branch" aria-label="Venues">
<li><a class="stop" href="#" data-stop="docks">Old Docks</a></li>
<li><a class="stop" href="#" data-stop="glasshouse" data-autoclic>Glasshouse</a></li>
<li><a class="stop" href="#" data-stop="depot">Tram Depot</a></li>
</ol>
</li>
<li><a class="stop" href="#" data-stop="tickets" data-autoclic>Tickets</a></li>
</ol>
</nav>
<!-- the station board: the stop the car is at, or the one it is going to while it travels -->
<section class="board" aria-labelledby="board-title" data-board>
<p class="board__status">
<span class="board__state" data-status>Now at</span>
<span class="board__line" data-line>Canal line</span>
</p>
<h1 class="board__title" id="board-title"><span class="sr" data-title-name>Welcome</span><span aria-hidden="true" data-title>Welcome</span></h1>
<p class="sr" aria-live="polite" data-live></p>
</section>
</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>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.
28 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 menu della metropolitana» da Animorio e adattala al mio sitoOgni linea è una fila di punti; gli angoli si arrotondano con un raggio. Lo script ne fa pezzi dritti e archi, ognuno con la sua lunghezza e la sua curvatura (zero o 1/raggio), e scrive lo stesso tracciato come path SVG con i comandi L e A. Così per ogni distanza lungo la linea sa il punto, la direzione e quanto curva, senza getPointAtLength.
Un viaggio è fatto di tratti: lungo una linea, o fino allo scambio e poi sull’altra. Prima di partire lo script calcola un limite di velocità per ogni unità di strada: SPEED sul dritto, √(GRIP / curvatura) in curva, zero dove il vagoncino deve cambiare verso e alla fine; poi, camminando all’indietro, il limite può crescere solo quanto permette la frenata (v² = v₀² + 2·BRAKE·d). A ogni fotogramma il vagoncino accelera di PICKUP verso il limite, con il passo limitato a 1/30 di secondo.
La spinta di lato è v² per la curvatura: muove una molla sull’angolo della cassa, integrata a passi di 1/240 di secondo, che resta indietro entrando in curva e va un po’ oltre uscendone. L’ombra è tre rettangoli trasparenti uno sull’altro (niente filtro di sfocatura, che si ricalcolerebbe a ogni fotogramma) e si sposta verso l’esterno della curva.
Ogni viaggio stende la sua vernice: un path per tratto, con pathLength uguale alla sua lunghezza e uno stroke-dasharray che si scopre con stroke-dashoffset man mano che il vagoncino avanza. Lo spazio vuoto del tratteggio è più lungo della linea, così una linea non ancora scoperta non mostra nemmeno il pallino del bordo tondo. Alla partenza seguente la vernice vecchia sfuma.
Le fermate sono link sopra il disegno, messi in unità della piantina con le unità del contenitore (100cqi / 360), così crescono con lei. Il percorso in anteprima è un path tratteggiato sottile (stroke-dasharray 5 4) che marcia con un’animazione CSS. Lo stato del tabellone è solo una parola col suo colore: Now at in verde, Next stop in ambra. Le lettere del tabellone, in Doto, scorrono a caso e si fermano da sinistra a destra con un tween di GSAP.
| Nome | File | Di partenza | Cosa cambia |
|---|---|---|---|
SPEED | script.js | 360 | La velocità massima del vagoncino, in unità della piantina al secondo (la piantina è larga 360). |
PICKUP | script.js | 760 | Quanto in fretta prende velocità. |
BRAKE | script.js | 640 | Quanto forte frena prima di una fermata. |
GRIP | script.js | 1300 | Quanta spinta di lato regge in curva: più basso, più rallenta. |
TURNBACK | script.js | 0.3 | I secondi che aspetta dove deve cambiare verso. |
SWAY | script.js | 1 | Quanto ondeggia la cassa e quanto si sposta l’ombra nelle curve. |
DRAW | script.js | 1.6 | I secondi in cui la linea si disegna all’arrivo. |
Per il sito di un festival, di una città, di un museo con più sedi, di una conferenza con più sale, o per l’indice di una guida: dove le pagine sono davvero tappe di un percorso e un gruppo di sottopagine può stare su una diramazione. Da cinque a dieci fermate.
Il tabellone va sopra e la piantina sotto, larga quanto lo schermo fino a 420 pixel; le fermate crescono e si stringono con lei e restano grandi abbastanza per un dito. Senza puntatore non c’è il percorso in anteprima: il tocco fa partire subito il vagoncino.
Il vagoncino non viaggia: sparisce in dissolvenza e ricompare alla fermata scelta, mentre la strada fatta compare colorata in dissolvenza. La linea non si disegna all’arrivo, le lettere del tabellone non scorrono, il tratteggio del percorso non marcia e le fermate non sobbalzano.
GSAP 3.15.0, Overpass (font variabile) 5.3.0, Doto (font variabile) 5.3.0.
Compressi con gzip, i tre file della demo pesano 12 KB; le librerie: GSAP 28 KB.
Provata il 4 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.