Vai al contenuto
animorio
EN
Torna alla libreria

La lontra nel fiume

Hover, SVGGSAPImpegnativaPeso compresso: Demo 27 KBGSAP 28 KBGratisScarica lo zip

L’intestazione di una riserva naturale di fiume inventata, Holt, nello stile ricco e piena di dettagli: il fiume visto di lato, sopra e sotto l’acqua, al tramonto. Una lontra grande, col pelo bagnato, i baffi e le zampe palmate, galleggia sulla schiena battendo un sasso su una conchiglia, si strofina il muso, si tuffa, nuota sott’acqua fra le alghe e riemerge con un pesce che mangia a galla, poi rotola su sé stessa. Intorno un salice, un pontile, un tronco caduto con un martin pescatore che si tuffa, un airone, pesci, un gambero, ninfee, canne e libellule. Col puntatore o col dito vicino all’acqua si fanno cerchi e la lontra viene a curiosare.

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 otter in the river</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/fraunces@5.3.0/full.css">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/bricolage-grotesque@5.3.0/index.css">
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <!-- a made-up river reserve, Holt. A river seen from the side, above and below the water: hills in the haze, alders,
       birches and a heron on the far bank, a willow hanging over the water, a boardwalk, a fallen log with a kingfisher
       on its branch, banks with roots, stones and ferns, lily pads, eel grass, fish, a crayfish under a stone, light
       moving on the riverbed. A big otter floats on its back tapping a stone on a shell, grooms its face, rolls over,
       dives, swims under the water and comes up with a fish to eat. A pointer or a finger near the water makes rings,
       and the otter swims over to have a look. All drawn by the script -->
  <main class="riserva" data-riserva>
    <svg class="scena" data-scena viewBox="0 0 1600 900" preserveAspectRatio="xMidYMax slice" role="img" aria-labelledby="scena-nome">
      <title id="scena-nome">A river otter floating on its back by a boardwalk, grooming, diving and coming up with a fish, among lily pads, reeds, a willow and a kingfisher</title>
      <defs>
        <linearGradient id="g-cielo" x1="0" y1="0" x2="0" y2="1">
          <stop offset="0" stop-color="var(--cielo-alto)"/>
          <stop offset=".7" stop-color="var(--cielo)"/>
          <stop offset="1" stop-color="var(--cielo-basso)"/>
        </linearGradient>
        <radialGradient id="g-sole" cx=".5" cy=".5" r=".5">
          <stop offset="0" stop-color="var(--sole)" stop-opacity=".95"/>
          <stop offset=".3" stop-color="var(--sole)" stop-opacity=".5"/>
          <stop offset="1" stop-color="var(--sole)" stop-opacity="0"/>
        </radialGradient>
        <linearGradient id="g-nuvola" x1="0" y1="0" x2="0" y2="1">
          <stop offset="0" stop-color="#fffaf0"/>
          <stop offset=".6" stop-color="#fbe9cb"/>
          <stop offset="1" stop-color="#eec99a"/>
        </linearGradient>
        <linearGradient id="g-colline-1" x1="0" y1="0" x2="0" y2="1">
          <stop offset="0" stop-color="var(--collina-lontana)"/>
          <stop offset="1" stop-color="var(--cielo-basso)"/>
        </linearGradient>
        <linearGradient id="g-colline-2" x1="0" y1="0" x2="0" y2="1">
          <stop offset="0" stop-color="var(--collina-chiara)"/>
          <stop offset="1" stop-color="#b9c79a"/>
        </linearGradient>
        <linearGradient id="g-colline-3" x1="0" y1="0" x2="0" y2="1">
          <stop offset="0" stop-color="var(--collina)"/>
          <stop offset="1" stop-color="#83a873"/>
        </linearGradient>
        <linearGradient id="g-foschia" x1="0" y1="0" x2="0" y2="1">
          <stop offset="0" stop-color="var(--cielo-basso)" stop-opacity="0"/>
          <stop offset="1" stop-color="var(--cielo-basso)" stop-opacity=".55"/>
        </linearGradient>
        <linearGradient id="g-acqua" x1="0" y1="0" x2="0" y2="1">
          <stop offset="0" stop-color="var(--acqua-chiara)"/>
          <stop offset=".12" stop-color="var(--acqua)"/>
          <stop offset=".5" stop-color="var(--acqua-media)"/>
          <stop offset="1" stop-color="var(--acqua-fonda)"/>
        </linearGradient>
        <linearGradient id="g-velo" x1="0" y1="0" x2="0" y2="1">
          <stop offset="0" stop-color="var(--acqua)" stop-opacity=".3"/>
          <stop offset=".35" stop-color="var(--acqua-media)" stop-opacity=".34"/>
          <stop offset="1" stop-color="var(--acqua-fonda)" stop-opacity=".58"/>
        </linearGradient>
        <linearGradient id="g-raggio" x1="0" y1="0" x2="0" y2="1">
          <stop offset="0" stop-color="#fff6d6" stop-opacity=".55"/>
          <stop offset=".6" stop-color="#e8fff0" stop-opacity=".12"/>
          <stop offset="1" stop-color="#e8fff0" stop-opacity="0"/>
        </linearGradient>
        <linearGradient id="g-sabbia" x1="0" y1="0" x2="0" y2="1">
          <stop offset="0" stop-color="var(--sabbia)"/>
          <stop offset="1" stop-color="var(--sabbia-scura)"/>
        </linearGradient>
        <linearGradient id="g-riva" x1="0" y1="0" x2="0" y2="1">
          <stop offset="0" stop-color="var(--terra)"/>
          <stop offset=".45" stop-color="var(--terra-media)"/>
          <stop offset="1" stop-color="var(--terra-scura)"/>
        </linearGradient>
        <linearGradient id="g-pelo-galla" x1="0" y1="0" x2="0" y2="1">
          <stop offset="0" stop-color="var(--pelo-chiaro)"/>
          <stop offset=".28" stop-color="#b07c4e"/>
          <stop offset=".6" stop-color="var(--pelo)"/>
          <stop offset="1" stop-color="var(--pelo-scuro)"/>
        </linearGradient>
        <linearGradient id="g-pelo" x1="0" y1="0" x2="0" y2="1">
          <stop offset="0" stop-color="var(--pelo-scuro)"/>
          <stop offset=".55" stop-color="var(--pelo)"/>
          <stop offset="1" stop-color="#a87a4f"/>
        </linearGradient>
        <linearGradient id="g-testa" x1="0" y1="0" x2="0" y2="1">
          <stop offset="0" stop-color="var(--pelo-scuro)"/>
          <stop offset=".7" stop-color="var(--pelo)"/>
          <stop offset="1" stop-color="#94643d"/>
        </linearGradient>
        <linearGradient id="g-muso" x1="0" y1="0" x2="0" y2="1">
          <stop offset="0" stop-color="#d9b48a"/>
          <stop offset="1" stop-color="var(--pelo-chiaro)"/>
        </linearGradient>
        <radialGradient id="g-sasso" cx=".35" cy=".3" r=".8">
          <stop offset="0" stop-color="#d3ccbd"/>
          <stop offset=".55" stop-color="#9a9384"/>
          <stop offset="1" stop-color="#5a554c"/>
        </radialGradient>
        <radialGradient id="g-sasso-scuro" cx=".35" cy=".3" r=".8">
          <stop offset="0" stop-color="#a39a86"/>
          <stop offset=".6" stop-color="#6c665a"/>
          <stop offset="1" stop-color="#3d3a33"/>
        </radialGradient>
        <radialGradient id="g-sasso-caldo" cx=".35" cy=".3" r=".8">
          <stop offset="0" stop-color="#d8bf98"/>
          <stop offset=".6" stop-color="#9c7f5a"/>
          <stop offset="1" stop-color="#5e4a33"/>
        </radialGradient>
        <radialGradient id="g-foglia" cx=".4" cy=".35" r=".75">
          <stop offset="0" stop-color="var(--ninfea-chiara)"/>
          <stop offset="1" stop-color="var(--ninfea)"/>
        </radialGradient>
        <linearGradient id="g-ala" x1="0" y1="0" x2="1" y2="0">
          <stop offset="0" stop-color="#e9fbff" stop-opacity=".7"/>
          <stop offset="1" stop-color="#e9fbff" stop-opacity=".25"/>
        </linearGradient>
        <linearGradient id="g-pesce" x1="0" y1="0" x2="0" y2="1">
          <stop offset="0" stop-color="#5f6f43"/>
          <stop offset=".45" stop-color="#a9b382"/>
          <stop offset=".7" stop-color="#dfe3cf"/>
          <stop offset="1" stop-color="#f4f1e2"/>
        </linearGradient>
        <linearGradient id="g-pesce-2" x1="0" y1="0" x2="0" y2="1">
          <stop offset="0" stop-color="#6b5a33"/>
          <stop offset=".45" stop-color="#c2a463"/>
          <stop offset=".75" stop-color="#ead9ad"/>
          <stop offset="1" stop-color="#f6eedb"/>
        </linearGradient>
        <pattern id="p-squame" width="7" height="6" patternUnits="userSpaceOnUse">
          <path d="M0 3A3.5 3.5 0 0 0 7 3M-3.5 6A3.5 3.5 0 0 0 3.5 6M3.5 6A3.5 3.5 0 0 0 10.5 6M-3.5 0A3.5 3.5 0 0 0 3.5 0M3.5 0A3.5 3.5 0 0 0 10.5 0" fill="none" stroke="#2c3220" stroke-width=".7" opacity=".5"/>
        </pattern>
        <linearGradient id="g-martin-dorso" x1="0" y1="0" x2="0" y2="1">
          <stop offset="0" stop-color="#3fc0d6"/>
          <stop offset=".5" stop-color="#1886a8"/>
          <stop offset="1" stop-color="#0f5f7e"/>
        </linearGradient>
        <linearGradient id="g-martin-ventre" x1="0" y1="0" x2="0" y2="1">
          <stop offset="0" stop-color="#f3a04a"/>
          <stop offset="1" stop-color="#d9702a"/>
        </linearGradient>
        <linearGradient id="g-tronco" x1="0" y1="0" x2="0" y2="1">
          <stop offset="0" stop-color="#9b7a55"/>
          <stop offset=".5" stop-color="#6e5338"/>
          <stop offset="1" stop-color="#3e2d1d"/>
        </linearGradient>
        <linearGradient id="g-betulla" x1="0" y1="0" x2="1" y2="0">
          <stop offset="0" stop-color="#e9e2d4"/>
          <stop offset=".6" stop-color="#fbf7ee"/>
          <stop offset="1" stop-color="#cfc6b4"/>
        </linearGradient>
        <linearGradient id="g-salice" x1="0" y1="0" x2="0" y2="1">
          <stop offset="0" stop-color="#7fa54e"/>
          <stop offset="1" stop-color="#a9c867"/>
        </linearGradient>
        <linearGradient id="g-gambero" x1="0" y1="0" x2="0" y2="1">
          <stop offset="0" stop-color="#8a4a2a"/>
          <stop offset="1" stop-color="#c47a45"/>
        </linearGradient>
        <linearGradient id="g-riverbero" x1="0" y1="0" x2="0" y2="1">
          <stop offset="0" stop-color="var(--sole)" stop-opacity=".6"/>
          <stop offset="1" stop-color="var(--sole)" stop-opacity="0"/>
        </linearGradient>
        <clipPath id="c-sotto"><path data-clip-sotto d="M0 470H1600V900H0Z"/></clipPath>
      </defs>

      <rect width="1600" height="520" fill="url(#g-cielo)"/>
      <circle cx="1230" cy="160" r="260" fill="url(#g-sole)"/>
      <circle cx="1230" cy="160" r="46" fill="var(--sole)" opacity=".75"/>
      <g data-nuvole></g>
      <g data-lontano></g>
      <g data-pontile></g>

      <!-- under the water -->
      <path data-acqua fill="url(#g-acqua)" d="M0 470H1600V900H0Z"/>
      <g clip-path="url(#c-sotto)">
        <use href="#lontano-forme" data-riflesso opacity=".22" transform="translate(0 940) scale(1 -1)"/>
        <g data-strisce></g>
        <g data-raggi></g>
        <g data-fondale></g>
        <g data-caustiche></g>
        <g data-alghe></g>
        <g data-gambi></g>
        <g data-gambero></g>
        <g data-pesci></g>
        <g data-particelle></g>
        <g data-sotto-superficie></g>
      </g>
      <g data-rive-sotto></g>

      <!-- the lily pads, the otter in front of them, the kingfisher, the bubbles, then the water veil that tints everything under the surface -->
      <g data-ninfee></g>
      <g data-lontra></g>
      <g data-martin></g>
      <g data-bolle></g>
      <path data-velo fill="url(#g-velo)" d="M0 470H1600V900H0Z"/>

      <!-- on the surface and above it -->
      <path data-luccichio fill="none" stroke="var(--schiuma)" stroke-width="2.2" stroke-linecap="round" opacity=".55"/>
      <g data-riverbero></g>
      <g data-cerchi></g>
      <g data-schizzi></g>
      <g data-salice></g>
      <g data-canne></g>
      <g data-erba></g>
      <g data-libellula></g>
    </svg>

    <header class="testata">
      <p class="marchio">
        <svg viewBox="0 0 32 32" aria-hidden="true"><path d="M3 20c4-4 8-4 13 0s9 4 13 0M3 26c4-4 8-4 13 0s9 4 13 0M10 13c2-5 9-7 13-3"/></svg>
        Holt
      </p>
      <p class="sotto">River otter reserve</p>
    </header>

    <div class="testo">
      <h1 class="titolo">Wild water, <em>close up.</em></h1>
      <p class="riga">Watch the otters fish, play and dive along a mile of quiet river. Open dawn to dusk.</p>
      <div class="azioni">
        <a class="pillola" href="#visit"><span>Plan a visit</span></a>
      </div>
    </div>

    <p class="aiuto" data-aiuto>
      <svg viewBox="0 0 24 24" aria-hidden="true"><path d="M2 15c2.5-2.5 5-2.5 7.5 0s5 2.5 7.5 0 3.5-2 5 -.5M6 9.5a6 6 0 0 1 12 0"/></svg>
      <span>Move near the water</span>
    </p>
  </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.

45 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 «La lontra nel fiume» da Animorio e adattala al mio sito

Cosa fa

Una scena di fiume disegnata in SVG, a strati. Sopra: il cielo ocra del tardo pomeriggio con le nuvole che passano, tre file di colline nella foschia, ontani, betulle e pioppi sulla riva lontana e un airone fermo nell’acqua bassa che ogni tanto abbassa il collo; un salice che pende sull’acqua coi rami che ondeggiano; un pontile di assi con le venature, i chiodi e le alghe sui pali; un tronco caduto mezzo sommerso con le alghe e il ramo del martin pescatore, che ogni tanto si tuffa e torna con un pesciolino; le rive a strati di terra con le radici, i sassi col muschio, l’erba che pende sull’acqua, le felci, canne e tife. Sotto: l’acqua più scura con la profondità, la superficie vista da sotto, la riva lontana specchiata e spezzata dalle onde, il riverbero del sole, i raggi e le caustiche di luce che si muovono sul fondo, i granelli sospesi, sabbia, ghiaia, sassi, una cozza di fiume, un gambero che spunta da sotto un sasso, ciuffi di alghe, i gambi delle ninfee, tre pesci con le squame che scappano. La lontra è grande e fatta di parti incernierate: testa larga col muso chiaro, naso lucido, occhi col riflesso, baffi, pelo a due toni con le ciocche bagnate e il lucido, braccia corte con le dita, piedi palmati, coda spessa. Galleggia battendo il sasso, si strofina il muso, si tuffa, nuota con l’aria argentata sul dorso, riemerge sgocciolando, una volta su due con un pesce che mangia in tre morsi, poi rotola su sé stessa.

Come funziona

La superficie e il velo

superficie(x, t) somma due onde sinusoidali e le onde lasciate dagli spruzzi, che si allargano e si spengono. Con quella linea si chiudono tre forme: l’acqua dietro, il ritaglio di ciò che sta sotto (riflesso, raggi, fondale) e un velo traslucido davanti alla lontra. Così ciò che sta sotto la linea prende il colore del fiume, anche la metà della lontra che galleggia.

Le parti attaccate

La lontra è un gruppo con le sue parti: testa, zampe, piedi palmati e coda ruotano ognuna attorno al suo giunto (translate sul giunto, poi rotate). Le canne e le alghe sono lame che partono dalla base ferma e si piegano verso la punta; la testa della tifa si mette sulla curva al punto giusto e prende la sua tangente. Le ninfee seguono la superficie e il loro gambo va sempre fino al fondo.

Galleggiare e tuffarsi

Due disegni della lontra: sulla schiena e in nuoto. Il tuffo è una timeline: la lontra si gira, si abbassa col muso, lo spruzzo copre lo scambio dei due disegni, poi un valore p da 0 a 1 la porta sotto l’acqua lungo un arco (seno) e la ruota secondo la pendenza; alla fine un altro spruzzo e la risalita con back.out.

Spruzzi, cerchi e bolle

Lo spruzzo è una corona che si allarga e svanisce, gocce con la gravità che ricadono e fanno cerchi, un’onda sulla superficie e una spinta alle ninfee vicine. Le bolle salgono ondeggiando e scoppiano in superficie.

Il puntatore

Vicino all’acqua il puntatore lascia cerchi ogni tanto e piega le canne vicine; la lontra che galleggia si gira verso di lui, rema fin lì e lo guarda, e il tuffo aspetta finché resta curiosa.

Tanti dettagli, poco lavoro per fotogramma

Quasi tutta la scena si disegna una volta sola all’inizio (colline, alberi, rive a strati, sassi col muschio, pontile, fondale). A ogni fotogramma si ricalcolano solo le cose che si muovono: la superficie, le caustiche (sei punti per cella che oscillano), i granelli, le alghe, il salice, le canne, i pesci, il gambero, gli uccelli e la lontra. Niente filtri: le luci e le ombre sono sfumature e tratti.

Cosa fa la lontra

Una piccola macchina a stati con le timeline di GSAP: galleggia e batte il sasso, si strofina il muso con le zampe (il sasso resta sulla conchiglia), si tuffa, nuota, riemerge sgocciolando. Una volta su due riemerge con un pesce in bocca: lo tiene fra le zampe e lo mangia in tre morsi, poi rotola su sé stessa (il disegno sulla schiena e quello sul dorso si scambiano a metà giro) e si tuffa di nuovo.

Valori da cambiare

NomeFileDi partenzaCosa cambia
FLOAT_TIMEscript.js2.6I secondi in cui la lontra galleggia e batte il sasso prima di fare altro (lavarsi il muso, tuffarsi).
SWIM_TIMEscript.js2.8I secondi di nuoto sotto l’acqua.
DEPTHscript.js190Quanto scende nel tuffo, in unità della scena (1600 per 900).
WAVESscript.js1L’altezza delle piccole onde sulla superficie (0 = acqua ferma).
SWAYscript.js1Quanto ondeggiano le canne, il salice, l’erba, le felci e le alghe.
RIPPLESscript.js1La misura dei cerchi che il puntatore lascia sull’acqua.
CURIOUSscript.js1Quanto in fretta la lontra rema verso il puntatore (0 = non viene mai).

Provali nel Playground

Quando usarla

Come apertura di una riserva naturale, di un parco, di un acquario o di uno zoo, di un’associazione per la natura o di una guida di escursioni; in generale quando la prima schermata deve raccontare un posto vivo e far venire voglia di toccarlo.

Sul telefono

Le stesse animazioni a misure adattate: il titolo va in alto su tutta la larghezza, il fiume riempie il resto e la lontra si tuffa e riemerge dentro la parte visibile, che si misura a ogni cambio di misura. Il dito vicino all’acqua fa cerchi e chiama la lontra come il puntatore.

Con il movimento ridotto

Niente onde, tuffi, spruzzi, bolle né movimento: la scena è ferma, con la lontra che galleggia al suo posto; le scritte compaiono senza spostarsi.

Trappole

  • Il velo dell’acqua sta sopra la lontra ma sotto le ninfee e le canne: così la parte immersa prende il colore del fiume e quello che sta sopra resta pulito. Le canne nell’acqua hanno un gambo a parte, sotto il velo, fino al fondo.
  • Il tuffo scambia due disegni (sulla schiena e in nuoto): lo scambio avviene nello stesso istante dello spruzzo, che lo copre.
  • Le misure della parte visibile si ricalcolano al resize (preserveAspectRatio slice taglia i lati sul telefono): i due posti dove la lontra si tuffa e riemerge stanno sempre dentro.

Librerie

GSAP 3.15.0, Fraunces (font variabile) 5.3.0, Bricolage Grotesque (font variabile) 5.3.0.

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

Collaudo

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

Tutte le animazioni