
La macchina della colazione
Scroll, SVG, Fisica
NuovaGratis
Scorri dentro l’anteprima
Scorrendo, una ruota quadrata rotola su una strada di gobbe: sono archi di catenaria, la matematica vera della ruota quadrata, e il suo mozzo non si muove mai dalla linea tratteggiata. Strada facendo prende lati uno alla volta, da quattro a dodici, poi si gonfia fino al cerchio e la strada si spiana sotto di lei.
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 wheel that rounds off</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/bricolage-grotesque@5.3.0/standard.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/fraunces@5.3.0/full-italic.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/red-hat-mono@5.3.0/index.css">
<link rel="stylesheet" href="style.css">
</head>
<body>
<!-- a made-up bike workshop, Round Trip Cycle Works. The stage sticks while you scroll: a square wheel rolls along a
road of catenary arches (the real maths of the square wheel, drawn on a canvas), takes on sides from four to
twelve, swells into a circle and the road flattens out under it. The four steps of a service light up as the
wheel passes over them. Everything is drawn by the script -->
<main>
<section class="corsa" data-corsa>
<div class="palco" data-palco>
<canvas class="strada" data-strada aria-hidden="true"></canvas>
<header class="testa">
<a class="marchio" href="#" data-marchio>
<svg class="marchio__segno" viewBox="0 0 40 40" aria-hidden="true">
<rect class="marchio__ruota" data-marchio-ruota x="7" y="7" width="26" height="26" rx="7"/>
<path class="marchio__raggi" d="M20 9.5v21M9.5 20h21"/>
<circle class="marchio__mozzo" cx="20" cy="20" r="3.6"/>
</svg>
<span class="marchio__nome" data-entra-testa>Round Trip<span>Cycle Works</span></span>
</a>
<p class="testa__orari" data-entra-testa>Open Tuesday to Saturday</p>
<a class="pillola" href="#" data-pillola data-entra-testa><span class="pillola__fondo" data-pillola-fondo></span><span class="pillola__testo">Book a service</span></a>
</header>
<div class="apertura">
<p class="apertura__etichetta" data-entra>How a service goes</p>
<h1 class="apertura__titolo">
<span class="riga"><span class="riga__dentro" data-riga>From square one</span></span>
<span class="riga"><span class="riga__dentro morbido" data-riga data-morbido>to a smooth ride.</span></span>
</h1>
<p class="apertura__testo" data-entra>Bring us the bike that rattles. We take the corners off, one at a time, until it rolls like the day you bought it.</p>
</div>
<div class="bandiera" data-bandiera aria-hidden="true">
<div class="bandiera__telo" data-telo>
<span class="bandiera__nome" data-bandiera-nome>Square</span>
<span class="bandiera__lati" data-bandiera-lati>4 sides</span>
</div>
</div>
<p class="cenno" data-cenno>
<span>Scroll to roll</span>
<svg viewBox="0 0 20 20" aria-hidden="true"><path d="M10 3v13M4.5 10.5 10 16l5.5-5.5"/></svg>
</p>
<ul class="passi" data-passi>
<li class="passo" data-passo data-forma="primo">
<svg class="passo__forma" viewBox="-12 -12 24 24" aria-hidden="true"><path data-passo-forma/></svg>
<h2 class="passo__nome">Drop off</h2>
<p class="passo__riga">Wheel in, coffee on. We write down every rattle and squeak.</p>
</li>
<li class="passo" data-passo data-forma="medio">
<svg class="passo__forma" viewBox="-12 -12 24 24" aria-hidden="true"><path data-passo-forma/></svg>
<h2 class="passo__nome">Check-up</h2>
<p class="passo__riga">Spokes, bearings, brakes and chain. We find every corner.</p>
</li>
<li class="passo" data-passo data-forma="ultimo">
<svg class="passo__forma" viewBox="-12 -12 24 24" aria-hidden="true"><path data-passo-forma/></svg>
<h2 class="passo__nome">Tune</h2>
<p class="passo__riga">Trued, tensioned and greased, one side at a time.</p>
</li>
<li class="passo" data-passo data-forma="cerchio">
<svg class="passo__forma" viewBox="-12 -12 24 24" aria-hidden="true"><path data-passo-forma/></svg>
<h2 class="passo__nome">Ride away</h2>
<p class="passo__riga">Round, quiet and quick. Same day, most days.</p>
</li>
</ul>
<p class="passi__ora" aria-hidden="true"><span data-passo-ora>Wheel in, coffee on. We write down every rattle and squeak.</span></p>
</div>
</section>
</main>
<script src="https://cdn.jsdelivr.net/npm/gsap@3.15.0/dist/gsap.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/gsap@3.15.0/dist/ScrollTrigger.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/lenis@1.3.26/dist/lenis.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.
37 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 «La ruota che si arrotonda» da Animorio e adattala al mio sitoVisto dal mozzo, il contorno della ruota è una distanza r per ogni angolo. Se il mozzo resta alla stessa altezza e la ruota non scivola, il punto che tocca la strada è sempre proprio sotto il mozzo: lì la strada è r più in basso, e avanzando di dx la ruota gira di dx diviso r. Quindi la strada è x uguale alla somma di r per l’angolo, y uguale a r. Per un lato dritto a distanza d dal centro, r è d diviso il coseno dell’angolo dalla sua perpendicolare, e la somma viene d per asinh(tan(angolo)): un arco di catenaria rovesciato, d·cosh(x/d), largo quanto il lato. È la strada della ruota quadrata.
Fra n e n+1 lati la ruota non salta: il poligono riceve un vertice nuovo a metà del suo ultimo lato, poi tutti i vertici scivolano dove li ha il poligono con un lato in più, girato di quel poco che li fa muovere il meno possibile. I lati vanno da SIDES[0] a SIDES[1] nella prima metà della corsa (con una smoothstep), poi i lati si gonfiano: ogni punto del contorno va verso il raggio pieno, cioè r diventa lerp(r, 1, tondo), e la strada si calcola con la stessa r, così si spiana da sola.
Siccome la forma cambia mentre rotola, l’angolo della ruota non si legge dalla forma: si somma una volta sola, all’inizio, in 2.400 passi piccoli (dx diviso r, con un passo intermedio per essere precisi) e si tiene in una tabella. Ogni fotogramma legge la tabella al punto della corsa, così tornando indietro la ruota ripassa per le stesse posizioni.
ScrollTrigger dà la frazione di corsa; il disegno la insegue coprendo ogni fotogramma la quota CHASE della distanza (calcolata sul tempo vero, quindi uguale a 60 e a 120 Hz) e, quando la distanza è sotto 0,0005, si ferma lì. Il canvas si ridisegna solo se qualcosa è cambiato: la corsa, la bandierina che oscilla o la polvere ancora in aria.
Il palo della bandierina è una molla: si piega all’indietro con la velocità della ruota e riceve un colpo ogni volta che uno spigolo cade in una buca, tanto più forte quanto più la ruota è spigolosa; nello stesso momento parte uno sbuffo di polvere (DUST). Il nome della forma cambia sul numero di lati arrotondato, con un rimbalzo. Ogni passo si accende quando il mozzo supera l’inizio della sua colonna, e l’asse SOFT del Fraunces corsivo segue quanto la ruota è tonda.
| Nome | File | Di partenza | Cosa cambia |
|---|---|---|---|
SIDES | script.js | [4, 12] | I lati della ruota alla partenza (almeno 4: un triangolo urterebbe la gobba dopo) e quanti ne prende prima di diventare un cerchio; nel sito 4 e 12. |
RADIUS | script.js | 0.13 | Il raggio della ruota, in frazione del lato corto dello schermo (al telefono per 1,4); nel sito 0,13. |
CHASE | script.js | 0.2 | Quanta strada verso lo scorrimento fa il disegno a ogni fotogramma: 1 lo segue subito, 0,05 arriva molto morbido; nel sito 0,2. |
TYRE | script.js | 0.13 | Lo spessore del copertone, in frazione del raggio. |
DUST | script.js | 1 | Lo sbuffo di polvere quando uno spigolo cade in una buca (0 = niente). |
FLAG | script.js | 1 | Quanto la bandierina oscilla e rimbalza sul suo palo (0 = rigida). |
RIDE | script.js | 1 | Quanto scorrimento serve per tutta la corsa: 2 è il doppio. |
Per raccontare un metodo in pochi passi (un servizio, un processo, un percorso da A a B) dove l’idea è «da spigoloso a liscio»: officine, studi, consulenze, app che promettono di semplificare. La ruota fa capire il miglioramento senza parole.
Uguale: la ruota è un po’ più grande in proporzione, i quattro passi stanno in fila con il solo nome e la riga del passo raggiunto compare sotto, cambiando con un rimbalzo.
La ruota non rotola: aspetta ferma a ogni passo, con la forma che ha lì, e il disegno passa da una sosta all’altra con una dissolvenza. Niente polvere, bandierina dritta, entrata solo in dissolvenza.
GSAP 3.15.0, Lenis 1.3.26, Bricolage Grotesque (font variabile) 5.3.0, Fraunces (font variabile) 5.3.0, Red Hat Mono (font variabile) 5.3.0.
Compressi con gzip, i tre file della demo pesano 14 KB; le librerie: GSAP + ScrollTrigger 45 KB, Lenis 5,3 KB.
Provata il 13 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.