Vai al contenuto
animorio
EN
Tutti i componenti

Le reazioni che fanno il giro

Chat, SVG, Transizioni, HoverGSAPImpegnativaPeso compresso: Demo 17 KBGSAP 28 KBGratisScarica lo zip

Gli annunci di una società di corsa, dove i soci possono solo reagire. Ogni reazione è disegnata con una riga sola, come i disegni che i podisti tracciano sulla mappa col percorso. Scelta dalla barra, il disegno si srotola in una linea che fa il giro del messaggio come una traccia GPS, ridisegna la reazione al suo posto sotto di lui e poi si riavvolge dietro di lei come un metro a nastro: la reazione atterra con un sobbalzo e il numero rotola avanti. Toccata sotto il messaggio, fa il giro completo e torna da dove è partita; tolta, si srotola e corre via all'indietro.

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 reactions that run a lap</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/archivo@5.3.0/wdth.css">
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <main class="stage">
    <!-- the announcements of a running club: a reaction leaves the bar as a line, runs a lap round the message like a
         GPS trace and zips into its place under it, drawing itself there; taken back, it unravels and runs off -->
    <section class="chat" aria-label="Lockside Run Club, announcements" data-chat data-autoclic>
      <header class="chat__head">
        <svg class="chat__mark" viewBox="0 0 44 44" aria-hidden="true">
          <rect class="mark__track" x="7" y="13.5" width="30" height="17" rx="8.5"/>
          <rect class="mark__lane" x="12.5" y="18.5" width="19" height="7" rx="3.5"/>
          <path class="mark__line" d="M22 13.5v5"/>
        </svg>
        <div class="chat__title">
          <h2 class="chat__name">Lockside Run Club</h2>
          <p class="chat__sub">Announcements · 46 members</p>
        </div>
      </header>

      <div class="chat__thread" data-thread>
        <div class="chat__content" data-content>
          <ol class="chat__log" data-log>
            <li class="msg" data-reactions="kudos 9, love 3" style="--face: #f0915f">
              <div class="msg__row">
                <span class="msg__face" aria-hidden="true">M</span>
                <div class="bubble" data-bubble>
                  <p class="bubble__who">Maya</p>
                  <p class="bubble__text">Sunday long run: 18 km from the lock gates, 8:00 sharp.<span class="bubble__room" aria-hidden="true"></span></p>
                  <span class="bubble__time">07:12</span>
                </div>
              </div>
              <div class="chips" role="group" aria-label="Reactions to Maya’s message" data-chips></div>
            </li>
            <li class="msg" data-reactions="kudos 6" style="--face: #6aa6ff">
              <div class="msg__row">
                <span class="msg__face" aria-hidden="true">J</span>
                <div class="bubble" data-bubble>
                  <p class="bubble__who">Jonah</p>
                  <p class="bubble__text">Track night moves to Thursday, the stadium has a concert.<span class="bubble__room" aria-hidden="true"></span></p>
                  <span class="bubble__time">08:40</span>
                </div>
              </div>
              <div class="chips" role="group" aria-label="Reactions to Jonah’s message" data-chips></div>
            </li>
            <li class="msg" data-reactions="fire 7, medal 4" style="--face: #c79bff">
              <div class="msg__row">
                <span class="msg__face" aria-hidden="true">P</span>
                <div class="bubble" data-bubble>
                  <p class="bubble__who">Priya</p>
                  <p class="bubble__text">Saturday’s results: Dev ran the 10K in 38:41, a new club record!<span class="bubble__room" aria-hidden="true"></span></p>
                  <span class="bubble__time">18:05</span>
                </div>
              </div>
              <div class="chips" role="group" aria-label="Reactions to Priya’s message" data-chips></div>
            </li>
            <li class="msg" data-reactions="haha 12" data-mine="haha" style="--face: #6aa6ff">
              <div class="msg__row">
                <span class="msg__face" aria-hidden="true">J</span>
                <div class="bubble" data-bubble>
                  <p class="bubble__who">Jonah</p>
                  <p class="bubble__text">Lost and found: one left shoe, size 42. Smells heroic.<span class="bubble__room" aria-hidden="true"></span></p>
                  <span class="bubble__time">18:31</span>
                </div>
              </div>
              <div class="chips" role="group" aria-label="Reactions to Jonah’s message" data-chips></div>
            </li>
          </ol>
          <!-- the lines that run, above the messages -->
          <svg class="chat__runs" aria-hidden="true" data-runs></svg>
        </div>
      </div>

      <footer class="chat__foot">
        <svg viewBox="0 0 24 24" aria-hidden="true"><rect x="5" y="10.5" width="14" height="10" rx="2.5"/><path d="M8 10.5V8a4 4 0 0 1 8 0v2.5"/></svg>
        <span>Only run leaders can post here</span>
      </footer>

      <p class="sr" aria-live="polite" data-say></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>

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.

79 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 «Le reazioni che fanno il giro» da Animorio e adattala al mio sito

Cosa fa

Su un fondo nero una chat scura larga 390 pixel: in alto il tondo con la pista disegnata, Lockside Run Club e Announcements · 46 members; sotto, quattro annunci di Maya, Jonah e Priya, ognuno col tondo dell'iniziale, il nome dentro la nuvoletta e l'ora in basso a destra, e sotto ogni annuncio le sue reazioni: piccole pillole con un disegno a una riga nel suo colore (Kudos blu, Love rosa, Haha giallo, Fire arancio, Fast verde acqua, Medal viola) e il numero. La mia reazione ha la pillola tinta e il bordo nel suo colore. In fondo, il lucchetto e Only run leaders can post here. Passando col puntatore su un annuncio compare accanto il pulsante tondo per reagire; tenendoci sopra il puntatore, cliccandolo, o col dito tenuto premuto sull'annuncio, sopra di lui si apre una barra scura con le sei reazioni che entrano una dopo l'altra con un rimbalzo, mentre gli altri annunci si attenuano. La reazione sotto il puntatore, il dito o i tasti si alza e si ingrandisce col suo nome sopra. Scelta, la barra se ne va e il suo disegno resta lì e si srotola: la linea, con una freccetta in testa, scende fino all'annuncio e gli corre intorno a pochi pixel dal bordo, sopra, giù per un fianco (passando anche dietro il tondo dell'iniziale) e sotto le reazioni, poi risale dentro la pillola e ridisegna la reazione tratto per tratto. Per un istante il percorso intero, dal disegno nella barra a quello nella pillola, abbraccia il messaggio; poi la coda parte e si riavvolge sempre più veloce, il disegno nella barra si srotola e tutta la linea finisce dentro la reazione, che si gonfia e torna giù con un rimbalzo, si scalda e si raffredda nel colore, mentre il numero sale rotolando e la pillola si tinge. Una reazione nuova apre il suo posto vuoto quando la linea si avvicina. Toccando la reazione di qualcun altro, la linea parte dalla pillola stessa, fa il giro completo del messaggio e torna lì; toccando la propria, il disegno si srotola fuori dalla pillola, corre via all'indietro lungo il bordo e svanisce, il numero scende e, se era l'ultima, la pillola si chiude e le altre scivolano a prendere il posto. Cambiando reazione, la vecchia se ne va e la nuova arriva insieme. Per il primo annuncio, che non ha spazio sopra, la barra si apre sotto e il giro è completo su quattro lati.

Come funziona

Disegni a una riga sola

Ogni reazione è un solo path SVG in un quadrato di 24 unità, disegnato da noi in modo che cominci e finisca al suo piede, dove la linea entra ed esce: il pollice parte dalla riga fra polsino e mano, il cuore dalla punta, la faccina da un punto in basso a sinistra del cerchio. I dettagli che non stanno in una riga (gli occhi, la bocca, il cuore della fiamma) si disegnano dopo. Ogni disegno si campiona una volta con getPointAtLength ogni mezza unità; il tratto è vector-effect: non-scaling-stroke, così è largo LINE pixel a 20 come a 28.

Il giro intorno al messaggio

La strada è una spezzata di angoli a GAP pixel dal messaggio: sopra la nuvoletta, giù per un fianco, sotto la riga delle reazioni, poi su dentro la pillola. Le misure vengono da offsetLeft e offsetTop sommati fino alla conversazione, non da getBoundingClientRect, così le trasformazioni in corso (la nuvoletta premuta, le pillole che scivolano) non ingannano. Ogni angolo si arrotonda col suo raggio (quello della nuvoletta o della pillola più GAP): l'arco parte a r·tan(φ/2) dall'angolo, col centro sul lato verso cui si gira, e si campiona ogni due pixel; i tratti dritti bastano i due capi. Il verso si sceglie perché il giro tocchi sempre tre lati: dalla metà sinistra della barra in senso orario, dalla destra in senso antiorario passando dietro il tondo dell'iniziale; con la barra sotto il messaggio, o partendo da una pillola, il giro è completo e prende il verso che non si incrocia.

Una finestra su una linea sola

Il disegno nella barra (percorso all'indietro, così la linea esce dal suo piede senza tornanti), il giro e il disegno nella pillola diventano una sola spezzata con le lunghezze cumulate. A ogni fotogramma se ne disegna solo una finestra [coda, testa], trovando i capi con una ricerca binaria: la testa va da un capo all'altro in LAP secondi con power2.inOut, la coda aspetta il 90% di LAP e poi parte con power3.in in ZIP secondi, così la linea si riavvolge come un metro a nastro. La linea è larga come i disegni dove li disegna e TRAIL sul giro, con tre gradini da 6 pixel per parte; la freccetta in testa si orienta sulla tangente presa 2,5 pixel prima e dopo, e compare solo sul giro.

Il posto e l'atterraggio

Prima di ogni cambio si legge dove sta ogni pillola, poi le pillole che si spostano partono dal posto vecchio (FLIP). Una pillola che se ne va resta dov'era, fuori dalla fila in posizione assoluta, mentre si chiude; una nuova entra subito nella fila, vuota e invisibile, così la strada sa dove finire, e si apre con back.out a metà del giro. Atterrando, la pillola si gonfia di BOUNCE e torna con elastic.out, il riempimento del disegno passa da fill-opacity 0,85 a 0,22 e il numero rotola: il vecchio esce in alto, il nuovo entra dal basso con back.out, e la larghezza segue con un tween.

Andarsene all'indietro

Togliendo la propria reazione la finestra corre all'indietro: il capo davanti con power2.out, quello dietro con power2.in, finché si incontrano qualche centinaio di pixel prima (al massimo 230) e la linea svanisce. Così il disegno si srotola dalla sua fine mentre la testa corre via, e la pillola, se era l'ultima reazione, si chiude subito dopo.

Barra, tasti e dito

La barra è un role toolbar con un tabindex che gira: frecce, Home e Fine si spostano, Invio sceglie, Esc chiude e riporta il fuoco al pulsante React, Tab chiude e prosegue da lì. Ogni pulsante ha aria-label (React with Kudos to Maya’s message) e aria-pressed per la propria reazione, e un annuncio aria-live dice cosa è cambiato. Il puntatore fermo 0,24 secondi sul pulsante apre la barra; il dito tenuto HOLD secondi sull'annuncio la apre e, finché quel dito la tiene aperta, un touchmove non passivo impedisce allo scorrimento di partire, così si può scivolare fino a una reazione e alzare il dito per sceglierla. L'anteprima della libreria apre la barra, prova le reazioni e ne sceglie una senza prendere il fuoco.

Valori da cambiare

NomeFileDi partenzaCosa cambia
REACTIONSscript.js[['kudos', 'Kudos'], ['love', 'Love'], ['haha', 'Haha'], ['fire', 'Fire'], ['fast', 'Fast'], ['medal', 'Medal']]Le reazioni della barra: il disegno (kudos, love, haha, fire, fast o medal) e il nome che si legge e si sente.
LAPscript.js0.62I secondi del giro, dalla barra intorno al messaggio fino alla reazione sotto di lui.
ZIPscript.js0.34I secondi in cui il resto della linea si riavvolge dietro la testa quando è arrivata.
GAPscript.js7A quanti pixel dal messaggio corre la linea.
LINEscript.js2La larghezza dei disegni, e della linea dove li disegna, in pixel.
TRAILscript.js3La larghezza della linea durante il giro, in pixel.
HOLDscript.js0.42I secondi col dito fermo su un messaggio per aprire la barra.
BOUNCEscript.js0.16Quanto si gonfia una reazione quando la linea ci atterra.
DEMOscript.js[[2, 'medal', 'bar'], [1, 'kudos', 'bar'], [2, 'fire', 'bar'], [1, 'kudos', 'chip'], [2, 'fire', 'chip']]L'anteprima della libreria, un passo per clic: il messaggio (da 0), la reazione, e se dalla barra o dalla pillola sotto il messaggio. I cinque passi tornano allo stato di partenza.

Provali nel Playground

Quando usarla

Per le reazioni ai messaggi di una chat di gruppo, di un canale di annunci, dei commenti di una community o di un'app sportiva: ovunque una reazione debba sentirsi consegnata al messaggio, e non solo contata.

Sul telefono

La chat prende la larghezza dello schermo meno i margini (358 pixel a 390). Il dito tenuto sull'annuncio apre la barra (la nuvoletta si abbassa un poco mentre aspetta, e il menu del telefono e la selezione del testo restano chiusi); si sceglie toccando, o scivolando col dito fino alla reazione e alzandolo. Le reazioni sono alte 30 pixel ma il bersaglio è di 44, e sotto i 420 pixel il pulsante React, che serve ai tasti e al mouse, lascia il suo spazio alle nuvolette e va in fondo alla riga delle reazioni.

Con il movimento ridotto

Niente linea e niente spostamenti: la barra compare e scompare sfumando, la reazione scelta cambia colore e numero con una dissolvenza al suo posto, una pillola nuova compare e una tolta svanisce; gli altri annunci si attenuano lo stesso mentre la barra è aperta.

Trappole

  • Col giro sempre in senso orario, scegliendo una reazione a destra della barra (sopra un messaggio corto) la linea faceva solo una L, giù e sotto: il verso si sceglie dalla metà della barra, così il giro tocca sempre tre lati.
  • Sopra il primo messaggio la barra finiva sulla testata e copriva il nome della chat, e l'inizio della linea restava nascosto sotto: quando sopra non c'è posto la barra si apre sotto il messaggio, e il giro diventa completo, nel verso che non si incrocia.
  • Misurando con getBoundingClientRect, la nuvoletta ancora premuta o le pillole a metà del loro scivolamento davano posti sbagliati e la linea entrava di traverso: si misura con offsetLeft e offsetTop, che ignorano le trasformazioni.
  • Partendo dalla fine del disegno nella barra la linea faceva un tornante per scendere: il disegno nella barra si percorre all'indietro, così la linea esce dal suo piede, come ci entra nella pillola.
  • Larga 2 pixel la linea nella miniatura del catalogo quasi non si vedeva: sul giro è larga TRAIL, e per non avere uno scalino dove incontra i disegni passa da una misura all'altra in tre gradini.
  • Sul telefono il pulsante React, che lì non si usa, rubava 52 pixel alle nuvolette: diventavano di tre righe e il primo messaggio finiva sotto la testata. Sotto i 420 pixel il pulsante esce dal flusso.
  • Un dito che dopo la pressione lunga scivola verso la barra fa partire lo scorrimento e il browser annulla il puntatore: finché la barra aperta da quel dito è aperta, un touchmove non passivo lo impedisce.

Librerie

GSAP 3.15.0, Archivo (font variabile) 5.3.0.

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

Collaudo

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