Vai al contenuto
animorio
EN
Tutti i componenti

Il menu a mobile sospeso

Menu, Fisica, Hover, TransizioniCanvas, GSAPImpegnativaPeso compresso: Demo 14 KBGSAP 28 KBGratisScarica lo zip

Il menu di una piccola galleria come un mobile sospeso alla Calder: a riposo è un pulsante da cui pende un filo con una piccola copia della forma della pagina in cui sei. Premendo, il filo scende e i bracci di fil di ferro si aprono uno sotto l’altro, ognuno appeso al braccio di sopra; ogni voce è una forma piatta dipinta (petalo, disco, mezzaluna) appesa a un’estremità. L’equilibrio è vero: il mobile oscilla e si assesta dove i momenti dei pesi si pareggiano. Al passaggio la forma gira sul suo filo e il suo braccio si inclina sotto il peso; si può prendere e far dondolare tutto.

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 hanging mobile menu</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/bricolage-grotesque@5.3.0/standard.css">
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <main class="stage">
    <!-- the hanging mobile menu: the menu of a small gallery as a hanging mobile. Closed, it is a button with a thread
         hanging from it and, at its end, a little copy of the shape of the page you are on. Pressed, the thread drops
         and the wire arms open one under the other, each balanced under its own thread; every entry is a flat painted
         shape hanging at the end of an arm. The arms really balance: every shape has its weight, and the mobile swings
         and settles where the moments of the forces even out -->
    <div class="mobile" data-mobile>
      <canvas class="mobile__canvas" aria-hidden="true" data-canvas></canvas>

      <nav class="mobile__nav" id="mobile-menu" aria-label="Main" data-nav inert>
        <ul class="mobile__list">
          <li><a class="piece" href="#exhibitions" style="--c: var(--red)" data-piece="petal" aria-current="page"><span class="piece__label">Exhibitions</span></a></li>
          <li><a class="piece" href="#artists" style="--c: var(--black)" data-piece="disc"><span class="piece__label">Artists</span></a></li>
          <li><a class="piece" href="#collection" style="--c: var(--yellow)" data-piece="moon"><span class="piece__label">Collection</span></a></li>
          <li><a class="piece" href="#visit" style="--c: var(--blue)" data-piece="leaf"><span class="piece__label">Visit</span></a></li>
          <li><a class="piece" href="#journal" style="--c: var(--white)" data-piece="dot"><span class="piece__label">Journal</span></a></li>
        </ul>
      </nav>

      <button class="hanger" type="button" aria-expanded="false" aria-controls="mobile-menu" data-hanger data-autoclic>
        <span class="hanger__bg" aria-hidden="true" data-bg></span>
        <span class="hanger__icon" aria-hidden="true">
          <svg class="hanger__glyph" viewBox="0 0 24 24" data-glyph>
            <path class="glyph__wire" d="M12 2.5V7M4.5 10.5Q12 5.5 19.5 10.5M4.5 10.5V13M19.5 10.5V12.5"/>
            <path class="glyph__shape glyph__shape--red" d="M4.5 13c2.6.8 3.2 4.4.4 6.6-2.4-.9-3.1-4.4-.4-6.6z"/>
            <path class="glyph__shape" d="M19.5 12.5a3.6 3.6 0 1 1 0 7.2 3.6 3.6 0 0 1 0-7.2z"/>
          </svg>
          <svg class="hanger__cross" viewBox="0 0 24 24" data-cross>
            <path d="M6.5 6.5l11 11M17.5 6.5l-11 11"/>
          </svg>
        </span>
        <span class="hanger__words" aria-hidden="true">
          <span class="hanger__word" data-word="menu">Menu</span>
          <span class="hanger__word" data-word="close">Close</span>
        </span>
        <span class="sr" data-name>Open the menu</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.

29 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 menu a mobile sospeso» da Animorio e adattala al mio sito

Cosa fa

Su un fondo bianco un pulsante nero a pillola con Menu e un piccolo mobile disegnato; sotto, da un occhiello d’ottone, pende un filo sottile con una copia piccola del petalo rosso di Exhibitions, la pagina in cui sei, e la sua ombra morbida sul muro. Passandoci sopra la scritta si allarga, la pillola si gonfia con un rimbalzo e il petalo dondola. Premendo, il filo scende e i bracci di acciaio si aprono uno sotto l’altro, ognuno appeso con un filo all’estremità del braccio di sopra: a ogni estremità libera cresce una forma dipinta con la sua didascalia, Exhibitions (petalo rosso), Artists (disco nero), Collection (mezzaluna gialla), Visit (petalo blu), Journal (disco bianco). I bracci si aprono, dondolano e si fermano in piano, perché ognuno è appeso proprio dove i pesi dei due lati si pareggiano; il pulsante dice Close. Le forme sono lamiere sottili: girando sul filo si stringono, mostrano il bordo, e la luce scorre sulla vernice. Passando sopra una forma, la sua didascalia si allarga e si scurisce, la forma gira piano sul suo filo e pesa un poco di più: il suo braccio si inclina e quelli sopra rispondono. Una forma si può prendere col puntatore e tirare: tutto il mobile dondola e, lasciata, continua da solo. Scegliendo una voce, la sua forma scende un poco sul filo e fa un giro nella luce, le altre si raccolgono, i bracci si ripiegano dal basso e il filo risale nel pulsante portando la copia piccola della forma scelta. Da tastiera le frecce scorrono le voci (la forma col fuoco gira e pesa), Invio sceglie, Esc chiude; un clic fuori chiude.

Come funziona

Punti, pesi e fili

Il mobile è un insieme di punti con un peso: il perno e le due estremità di ogni braccio (fil di ferro leggero) e una forma per voce (pesante, circa quanto la sua superficie). I punti si muovono con passi di Verlet a 1/120 di secondo, con la gravità e uno smorzamento esponenziale; i fili sono vincoli che tirano soltanto (una distanza massima), risolti dieci volte per passo pesando ogni correzione sull’inverso della massa (position based dynamics). Il passo fisso tiene la fisica uguale a ogni frequenza dello schermo.

Ogni braccio appeso nel punto giusto

Dal basso verso l’alto lo script somma il peso che pende sotto ogni estremità e mette il perno di ogni braccio dove peso a sinistra per il suo braccio è uguale a peso a destra per il suo: così il mobile, lasciato andare, si ferma in piano da solo. Il perno sta un poco sopra la linea delle estremità (CURVE), come nei bracci curvi dei mobili veri: è questo che rende l’equilibrio stabile, e fa sì che un peso in più inclini il braccio di un angolo giusto invece di ribaltarlo.

Bracci rigidi con lo shape matching

I tre punti di un braccio, dopo ogni giro sui fili, vengono rimessi sulla loro forma: si cerca la rotazione che li accosta meglio (in due dimensioni un solo atan2 sulle somme dei prodotti scalari e vettoriali) e la si applica intorno al loro centro. Una rotazione non specchia mai, quindi un braccio non si ribalta nemmeno mentre si apre da un punto solo. Dei legami lunghi dall’occhiello a ogni punto, lunghi quanto filo e ferro fra i due, impediscono alla catena di pezzi pesanti di allungarsi a ogni giuntura.

Aprire, chiudere, scegliere

Una timeline di GSAP fa scendere il filo di ogni braccio (sine.inOut, mai più svelto della caduta libera, così non dà strappi) e allarga il braccio dal suo perno, uno dopo l’altro a STAGGER secondi; le forme crescono con elastic.out. La timeline va avanti con lo stesso orologio della fisica, a passi di 1/120: su un computer lento rallentano insieme. Scegliendo, il filo della forma si allunga di DROP e le altre si stringono a zero; poi i bracci si ripiegano dal basso e il primo filo torna corto, con la copia piccola della forma scelta.

Lamiere che girano nella luce

Ogni forma è un Path2D disegnato sul canvas dal punto a cui è appesa, girato come il suo filo. Gira anche intorno al filo: la larghezza si moltiplica per il coseno dell’angolo, sotto la forma si vede una copia scura spostata del seno (il bordo della lamiera), il colore si schiarisce quanto la faccia guarda la lampada e una banda di luce scorre da un lato all’altro. Sotto il puntatore la forma gira a SPIN giri al secondo e il suo peso diventa HEAVY volte: il braccio si inclina per i momenti nuovi. L’ombra sul muro è lo stesso disegno su un canvas grande un quarto, ingrandito: si sfuma da sé, senza il filtro blur.

Link veri e tastiera

Le voci sono link in un nav (inert quando è chiuso) e seguono le forme a ogni fotogramma, con la didascalia sotto; l’uscita dal passaggio si misura dalla forma e non dal riquadro, così la forma che scende sotto il mouse non perde il passaggio. Trascinandone una, il punto segue la mano con un limite morbido (tanh); un tocco senza trascinare sceglie. Il pulsante ha aria-expanded e aria-controls, le frecce, Home e End spostano il fuoco, Esc chiude e riporta il fuoco al pulsante, un’area aria-live dice la voce scelta. Quando niente si muove il ciclo si ferma.

Valori da cambiare

NomeFileDi partenzaCosa cambia
GRAVITYscript.js2400Quanto forte le forme sono tirate in giù, in unità del disegno al secondo quadrato: più forte, il mobile dondola più svelto.
DAMPINGscript.js2.2Quanto in fretta si spegne il dondolio, al secondo (0 = non si ferma mai).
HEAVYscript.js1.14Quante volte diventa più pesante una forma sotto il puntatore: il suo braccio si inclina sotto il peso.
SPINscript.js0.32Quanti giri al secondo fa una forma sul suo filo sotto il puntatore.
CURVEscript.js0.11Quanto si inarca ogni braccio sopra il suo perno, come parte della sua lunghezza: più alto, si inclina meno.
STAGGERscript.js0.2I secondi fra l’apertura di un braccio e quella del successivo.
DROPscript.js30Quanto scende sul suo filo la forma scelta prima che il mobile si ripieghi.

Provali nel Playground

Quando usarla

Per il menu di un sito dove la forma e il colore contano: una galleria, un museo, uno studio di design o di architettura, un negozio di oggetti, un portfolio. Da quattro a sei voci brevi; ogni voce si fa riconoscere dalla sua forma, e la copia piccola appesa al pulsante dice in che pagina sei anche da chiuso.

Sul telefono

Tutto il mobile si scala sulla larghezza dello schermo (a 390 pixel il riquadro è largo 358) e ci sta aperto, con le didascalie mai sotto gli 11,5 pixel. Il dito che tiene una forma vale come il passaggio del mouse (gira e pesa), trascinandola fa dondolare tutto, un tocco la sceglie; le forme tengono touch-action: none perché il dito non faccia scorrere la pagina.

Con il movimento ridotto

Niente dondolii né giri: il mobile si apre e si chiude con una dissolvenza, già in equilibrio al suo posto, e al passaggio cambia solo la didascalia. La voce scelta chiude il menu con la stessa dissolvenza e la sua copia piccola è già appesa al pulsante.

Trappole

  • Con tre vincoli di distanza per braccio, mentre il braccio si apriva da un punto solo, il primo braccio si ribaltava a specchio e restava capovolto: ora ogni braccio è rimesso sulla sua forma con una rotazione (shape matching), che non può specchiare.
  • Con il perno sulla linea delle estremità l’equilibrio era indifferente e i bracci restavano storti dove capitava: il perno sta sopra la linea, come nei bracci curvi veri.
  • In un browser lento la fisica, col passo limitato a 1/30, restava indietro rispetto alle timeline e i bracci si aprivano di colpo, sbattendo: le timeline ora vanno avanti con l’orologio della fisica.
  • Il filo che scendeva più svelto della caduta libera lasciava cadere le forme e poi le fermava di colpo, facendo rimbalzare tutto: il filo scende con sine.inOut e accompagna la caduta.
  • L’ombra sfumata con il filtro blur del canvas faceva scendere il computer di prova a pochi fotogrammi al secondo, e Safari non lo ha: l’ombra si disegna su un canvas piccolo e si ingrandisce.
  • La forma che si inclina e scende sotto il mouse usciva dal suo riquadro, perdeva il passaggio, tornava su e lo riprendeva, all’infinito: il passaggio finisce solo quando il puntatore si allontana dalla forma.
  • Trascinando una forma lontano, mezzo mobile usciva dal riquadro: la mano tira con un limite morbido.

Librerie

GSAP 3.15.0, Bricolage Grotesque (font variabile) 5.3.0.

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

Collaudo

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