Vai al contenuto
animorio
EN
Tutti i componenti

Tira per aggiornare

Caricamento, Fisica, TransizioniGSAPImpegnativaPeso compresso: Demo 8,1 KBGSAP 28 KBGratisScarica lo zip

Una lista di richieste che si aggiorna tirandola giù: segue la mano su un elastico che si fa più duro man mano, le righe si allargano un poco, un anello si riempie e oltre il segno la freccia si gira; lasciata lì, l’anello gira, si chiude in una spunta e le righe tornano su a onda mentre la richiesta nuova scende nello spazio.

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>Pull to refresh</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/golos-text@5.3.0/index.css">
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <main class="stage">
    <!-- pull to refresh: the list pulled down stretches like an elastic and a ring fills; let go past the mark and it
         refreshes, then the rows go back up in a wave and the new request drops into the space they leave -->
    <section class="inbox" aria-labelledby="inbox-title" data-inbox data-autoclic>
      <header class="inbox__head">
        <div>
          <h2 class="inbox__title" id="inbox-title">Requests</h2>
          <p class="inbox__when" data-when>Updated 5 min ago</p>
        </div>
        <button class="inbox__refresh" type="button" aria-label="Refresh" data-refresh>
          <svg viewBox="0 0 24 24" aria-hidden="true"><path d="M19.5 12a7.5 7.5 0 1 1-2.2-5.3"/><path d="M19.6 4.2v3.6H16"/></svg>
        </button>
      </header>
      <div class="inbox__body">
        <div class="ptr" aria-hidden="true" data-ptr>
          <svg class="ptr__ring" viewBox="0 0 40 40" data-ring>
            <circle class="ptr__track" cx="20" cy="20" r="16"/>
            <g data-spin>
              <circle class="ptr__arc" cx="20" cy="20" r="16" transform="rotate(-90 20 20)" data-arc/>
            </g>
            <path class="ptr__arrow" d="M20 13.5v13M15 21.5l5 5 5-5" data-arrow/>
            <path class="ptr__check" d="M14 20.5l4 4 8-8.5" data-check/>
          </svg>
          <span class="ptr__label" data-label>Pull to refresh</span>
        </div>
        <div class="inbox__scroll" data-scroll>
          <ul class="inbox__list" aria-labelledby="inbox-title" data-list></ul>
        </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>

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.

25 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 «Tira per aggiornare» da Animorio e adattala al mio sito

Cosa fa

Su un fondo nero un riquadro scuro con Requests, Updated 5 min ago e un pulsante tondo per aggiornare; sotto, sei richieste in schede scure, ognuna col suo tondo colorato con le iniziali, il nome, il messaggio e quanto tempo fa (Hannah Brooks, Leo Marchetti, Sara Lindqvist, Omar Haddad, Chloé Martin, Ben Okafor). Tirando giù la lista dall’alto, col dito, col mouse o col trackpad, la lista segue su un elastico che si fa più duro man mano, le righe si allontanano un poco l’una dall’altra e dietro compare un anello che si riempie di corallo, con una freccia e Pull to refresh; oltre il segno l’anello fa un piccolo balzo, la freccia si gira verso l’alto e la scritta diventa Release to refresh. Lasciando lì, la lista resta un poco giù mentre l’anello gira allungandosi e accorciandosi (Refreshing), poi si chiude e dentro si disegna una spunta (Up to date); le righe tornano su a onda, ognuna sulla sua molla, e dall’alto scende la richiesta nuova, contornata di corallo con l’etichetta New, mentre sopra si legge Updated just now. Lasciando prima del segno, la lista torna su senza aggiornarsi. Il pulsante tondo fa lo stesso, e la sua freccia gira finché non ha finito.

Come funziona

L’elastico

La distanza della mano diventa lo spostamento della lista con STRETCH × (1 − e^(−distanza ÷ STRETCH)): all’inizio la segue quasi uguale, poi sempre meno, e non va mai oltre STRETCH pixel. Si tira solo quando la lista è in cima, col dito, col mouse o con la rotella del trackpad (finché la rotella continua; quando si ferma, è come lasciare); altrimenti la lista scorre come sempre.

Le righe sulle molle

La prima riga segue la mano esattamente (con la rotella, che va a scatti, anche lei su una molla); ognuna delle altre va verso il suo posto su una molla (SPRING), calcolata sul ticker di GSAP a passi di 4 millisecondi, ogni volta un po’ più morbida di quella sopra (LAG): così, lasciata, la lista torna su a onda. I posti si allargano fino a SPREAD pixel per riga verso il limite dell’elastico, e una riga non passa mai sopra quella che la precede: se la raggiunge, viene spinta.

L’anello

Dietro la lista, un cerchio SVG il cui arco (stroke-dasharray) è la parte del segno (MARK) raggiunta, mentre l’anello cresce da 0,62 a 1; oltre il segno la freccia gira di 180 gradi con back.out e l’anello fa un balzo. Mentre aggiorna, l’arco gira e si allunga e si accorcia in loop; alla fine si chiude, finisce il suo giro invece di fermarsi dov’è, e dentro si disegna la spunta con stroke-dashoffset.

La richiesta nuova

Aggiunta in cima, sposta giù le altre nel layout: le loro molle tolgono subito quello spostamento, così restano dov’erano e poi scendono da sole; la nuova parte da sopra, nascosta sotto la testata, e scende al suo posto. Dopo un attimo perde il contorno e l’etichetta New. Le richieste sono al massimo otto: quando ne arriva una, la più vecchia se ne va.

Tasti e anteprima

Il pulsante tondo aggiorna anche coi tasti (prima porta la lista in cima, se era scesa); la lista ha aria-busy mentre si aggiorna, e una regione aria-live dice Refreshing e poi da chi è arrivata la richiesta nuova. Un clic da script (l’anteprima della libreria) è un dito finto: tira la lista oltre il segno, tiene un attimo e lascia.

Valori da cambiare

NomeFileDi partenzaCosa cambia
MARKscript.js84Di quanti pixel va tirata la lista perché, lasciandola, si aggiorni.
STRETCHscript.js170Il massimo che la lista si può tirare, in pixel: il limite dell’elastico.
SPREADscript.js10Di quanti pixel ogni riga si allontana da quella sopra, verso il limite.
SPRINGscript.js[380, 0.74]Le molle delle righe: quanto sono rigide e quanto sono frenate.
LAGscript.js0.35Quanto è più morbida ogni molla di quella sopra: l’onda.
LOADscript.js1.3I secondi di un aggiornamento (qui finto).
ARRIVALSscript.js[['Ines Duarte', 'Table for 2 tonight at 9, if anything is free?'], …]Le richieste che arrivano con un aggiornamento, una per volta.

Provali nel Playground

Quando usarla

Per le liste che cambiano da sole e si guardano spesso dal telefono: messaggi, prenotazioni, ordini, notizie, notifiche, una bacheca di annunci.

Sul telefono

Si tira col dito: sulla lista in cima il trascinamento in giù non fa scorrere la pagina (il touchmove si ferma solo allora), mentre in tutti gli altri casi la lista scorre come sempre, senza rimbalzare oltre il bordo (overscroll-behavior contain).

Con il movimento ridotto

La lista segue comunque la mano, ma senza molle né onda: lasciata, va subito al suo posto; l’anello e la freccia del pulsante non girano (l’anello è pieno mentre aggiorna), la spunta compare senza disegnarsi e la richiesta nuova compare già al suo posto.

Trappole

  • Una riga aggiunta in cima sposta tutte le altre nel layout: per farle scivolare si toglie lo spostamento dalle loro molle nello stesso momento (restano ferme dov’erano) e lo si lascia recuperare alle molle.
  • Al telefono il trascinamento in giù sulla lista in cima va fermato (touchmove con passive false e preventDefault), altrimenti Safari fa rimbalzare la pagina; solo allora, così lo scorrimento normale resta com’è.
  • Una linea con le estremità tonde e un tratto lungo zero (stroke-dashoffset uguale alla lunghezza) lascia comunque un puntino: la spunta resta nascosta finché non si disegna.
  • In una timeline che cambia una parola (esce, cambia il testo, entra) il fromTo dell’entrata vuole immediateRender false: altrimenti GSAP lo applica subito e la parola vecchia sparisce senza uscire.

Librerie

GSAP 3.15.0, Golos Text (font variabile) 5.3.0.

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

Collaudo

Provata il 3 ottobre 2026

  • Computer: Fatto
  • Telefono: Fatto
  • Movimento ridotto: Fatto
  • Safari su iPhone: Fatto

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