[ Web Proxy ]
URL:
Viewing: https://it.javascript.info/css-animations [Back]  [Original]

Animazioni CSS
IT

Vorremo rendere disponibile questo progetto open-source per persone in tutto il mondo.

Aiutaci a tradurre il contenuto di questo tutorial nella tua lingua!

    Cerca in Javascript.info:
    Cerca nel tutorial:
    Light themeDark theme
    DanskEnglishEspaolFranaisIndonesiaItalianoTrkeOzbek
    30 aprile 2022

    Animazioni CSS

    Le animazioni CSS ci consentono di realizzare semplici animazioni senza lutilizzo di JavaScript.

    JavaScript pu eventualmente essere utilizzato per controllare le animazioni CSS e migliorarle, aggiungendo qualche riga di codice.

    Transizioni CSS

    Lidea che sta alla base delle transizioni CSS molto semplice. Ci consente di definire come animare i cambiamenti su una determinata propriet. Quando il valore di questa propriet cambier, il browser mostrer lanimazione.

    Questo tutto, lunica cosa di cui abbiamo bisogno ora di cambiare il valore della propriet, e la transizione definita verr eseguita dal browser.

    Ad esempio, il codice CSS qui sotto definisce unanimazione al cambiamento della propriet background-color con durata 3 secondi:

    .animated {
      transition-property: background-color;
      transition-duration: 3s;
    }

    Quindi ora, se un elemento possiede la class .animated, qualsiasi cambiamento al suo background-color verr animato con una durata di 3 secondi.

    Provate a cliccare il bottone qui sotto per vedere lanimazione sul background:

    <button id="color">Click me</button>
    
    <style>
      #color {
        transition-property: background-color;
        transition-duration: 3s;
      }
    </style>
    
    <script>
      color.onclick = function() {
        this.style.backgroundColor = 'red';
      };
    </script>

    Abbiamo a disposizione 4 propriet per descrivere le transizioni CSS:

    • transition-property
    • transition-duration
    • transition-timing-function
    • transition-delay

    Le studieremo in dettaglio a breve, per ora notiamo che la propriet comune transition ci consente di dichiararle tutte insieme nellordine: property duration timing-function delay, e ci consente anche di definire pi propriet da animare.

    Ad esempio, nel bottone qui sotto abbiamo definito unanimazione sia su color che su font-size:

    <button id="growing">Click me</button>
    
    <style>
    #growing {
      transition: font-size 3s, color 2s;
    }
    </style>
    
    <script>
    growing.onclick = function() {
      this.style.fontSize = '36px';
      this.style.color = 'red';
    };
    </script>

    Ora, vediamo le propriet dellanimazione nel dettaglio.

    transition-property

    In transition-property, elenchiamo una lista di propriet da animare, ad esempio: left, margin-left, height, color. Oppure possiamo scrivere all, che significa anima tutte le propriet.

    Notiamo che ci sono propriet che non possono essere animate. Anche se la maggior parte delle propriet utilizzate sono animabili.

    transition-duration

    In transition-duration possiamo definire la durata dellanimazione. Il tempo deve essere nel formato temporale CSS: in secondi s o millisecondi ms.

    transition-delay

    In transition-delay possiamo specificare un ritardo dellanimazione. Ad esempio, se transition-delay impostato ad 1s e transition-duration vale 2s, allora lanimazione inizier con 1 secondo di ritardo rispetto al cambiamento del valore della propriet a cui fa riferimento, e avr una durata totale di 2 secondi.

    E possibile definire anche valori negativi. In questo caso lanimazione inizier immediatamente, ma il punto di inizio verr spostato di tanti secondi quanti sono quelli del tempo di ritardo fornito. Ad esempio, se transition-delay impostato a -1s e transition-duration vale 2s, lanimazione inizier a met ed avr una durata totale di 1 secondo.

    Qui vediamo un animazione che scorre le cifre da 0 a 9 utilizzando la propriet CSS translate:

    Risultato
    script.js
    style.css
    index.html
    stripe.onclick = function() {
      stripe.classList.add('animate');
    };
    #digit {
      width: .5em;
      overflow: hidden;
      font: 32px monospace;
      cursor: pointer;
    }
    
    #stripe {
      display: inline-block
    }
    
    #stripe.animate {
      transform: translate(-90%);
      transition-property: transform;
      transition-duration: 9s;
      transition-timing-function: linear;
    }
    <!doctype html>
    <html>
    
    <head>
      <meta charset="UTF-8">
      <link rel="stylesheet" href="style.css">
    </head>
    
    <body>
    
      Click below to animate:
    
      <div id="digit"><div id="stripe">0123456789</div></div>
    
      <script src="script.js"></script>
    </body>
    
    </html>

    La propriet transform viene animata in questo modo:

    #stripe.animate {
      transform: translate(-90%);
      transition-property: transform;
      transition-duration: 9s;
    }

    Nellesempio visto sopra, JavaScript aggiunge la classe .animate allelemento, iniziando cos lanimazione:

    stripe.classList.add('animate');

    Possiamo anche iniziarla a met della transizione, da un numero specifico, ad esempio corrispondente al secondo attuale, utilizzando un valore negativo per la propriet transition-delay.

    Nellesempio sotto, se cliccate il numero, lanimazione inizier dal secondo attuale:

    Risultato
    script.js
    style.css
    index.html
    stripe.onclick = function() {
      let sec = new Date().getSeconds() % 10;
      stripe.style.transitionDelay = '-' + sec + 's';
      stripe.classList.add('animate');
    };
    #digit {
      width: .5em;
      overflow: hidden;
      font: 32px monospace;
      cursor: pointer;
    }
    
    #stripe {
      display: inline-block
    }
    
    #stripe.animate {
      transform: translate(-90%);
      transition-property: transform;
      transition-duration: 9s;
      transition-timing-function: linear;
    }
    <!doctype html>
    <html>
    
    <head>
      <meta charset="UTF-8">
      <link rel="stylesheet" href="style.css">
    </head>
    
    <body>
    
      Click below to animate:
      <div id="digit"><div id="stripe">0123456789</div></div>
    
      <script src="script.js"></script>
    </body>
    </html>

    Con JavaScript possiamo fare la stessa cosa, ma con qualche riga di codice in pi:

    stripe.onclick = function() {
      let sec = new Date().getSeconds() % 10;
      // ad esempio, -3s in questo caso, far iniziare l'animazione al terzo secondo
      stripe.style.transitionDelay = '-' + sec + 's';
      stripe.classList.add('animate');
    };

    transition-timing-function

    La funzione di temporizzazione permette di descrivere la distribuzione dellanimazione lungo la sua durata. Potr iniziare pi lenta e poi accelerare, o vice versa.

    A prima vista sembra essere una delle propriet pi complesse. Ma diventa piuttosto semplice se ci dedichiamo un po di tempo per capirla.

    Questa propriet accetta due tipi di valore: una curva di Bezier oppure degli step. Iniziamo a vedere il caso in cui si utilizza la curva di Bezier, poich il pi comune.

    Bezier curve

    La funziona di temporizzazione pu essere definita utilizzando una curva di Bezier con 4 punti di controllo che soddisfino le seguenti condizioni:

    1. Il primo punto di controllo deve essere: (0,0).
    2. Lultimo punto di controllo deve essere: (1,1).
    3. Per i valori intermedi, il valore di x deve essere compreso nellintervallo 0..1, mentre y pu assumere qualsiasi valore.

    La sintassi per descrivere una curva di Bezier nel CSS: cubic-bezier(x2, y2, x3, y3). In questo caso necessario specificare solamente il terzo ed il quarto punto di controllo, poich il primo viene impostasto a (0,0) ed il quarto a (1,1).

    La funzione di temporizzazione descrive la velocit di riproduzione dellanimazione.

    • Lasse delle x rappresenta il tempo: 0 linizio, 1 il termine dellanimazione, specificato in transition-duration.
    • Lasse delle y specifica il completamento del processo: 0 il valore iniziale della propriet, 1 il valore finale.

    La variante pi semplice quando unanimazione procede uniformemente, con velocita lineare. Questo tipo di animazione pu essere definito con la curva cubic-bezier(0, 0, 1, 1).

    Cos come appare la curva descritta:

    []

    Come possiamo vedere, una semplice linea retta. Al passare del tempo (x), il completamento (y) dellanimazione passa da 0 a 1.

    Il treno nellesempio sotto va da sinistra verso destra con velocit costante (provate a cliccarci sopra):

    Risultato
    style.css
    index.html
    .train {
      position: relative;
      cursor: pointer;
      width: 177px;
      height: 160px;
      left: 0;
      transition: left 5s cubic-bezier(0, 0, 1, 1);
    }
    <!doctype html>
    <html>
    
    <head>
      <meta charset="UTF-8">
      <link rel="stylesheet" href="style.css">
    </head>
    
    <body>
    
      <img class="train" src="https://js.cx/clipart/train.gif" onclick="this.style.left='450px'">
    
    </body>
    
    </html>

    La transition CSS basata su questa curva:

    .train {
      left: 0;
      transition: left 5s cubic-bezier(0, 0, 1, 1);
      /* JavaScript imposta left a 450px */
    }

    Come potremmo mostrare il treno che rallenta?

    Possiamo utilizzare una curva di Bezier differente: cubic-bezier(0.0, 0.5, 0.5 ,1.0).

    La curva appare cos:

    []

    Come possiamo vedere, il processo inizia velocemente: la curva cresce verso lalto, e successivamente rallenta.

    Qui vediamo la funzione di temporizzazione in azione (cliccate il treno):

    Risultato
    style.css
    index.html
    .train {
      position: relative;
      cursor: pointer;
      width: 177px;
      height: 160px;
      left: 0px;
      transition: left 5s cubic-bezier(0.0, 0.5, 0.5, 1.0);
    }
    <!doctype html>
    <html>
    
    <head>
      <meta charset="UTF-8">
      <link rel="stylesheet" href="style.css">
    </head>
    
    <body>
    
      <img class="train" src="https://js.cx/clipart/train.gif" onclick="this.style.left='450px'">
    
    </body>
    
    </html>

    CSS:

    .train {
      left: 0;
      transition: left 5s cubic-bezier(0, .5, .5, 1);
      /* JavaScript imposta left a 450px */
    }

    Abbiamo a disposizione anche alcune curve integrate: linear, ease, ease-in, ease-out e ease-in-out.

    La curva linear un abbreviazione per cubic-bezier(0, 0, 1, 1), una linea retta, che abbiamo descritto sopra.

    Gli altri nomi sono delle abbreviazioni per le seguenti curve cubic-bezier:

    ease* ease-in ease-out ease-in-out
    (0.25, 0.1, 0.25, 1.0) (0.42, 0, 1.0, 1.0) (0, 0, 0.58, 1.0) (0.42, 0, 0.58, 1.0)
    []
    []
    []
    []

    * di default, se non viene fornita nessuna funzione di temporizzazione, verr utilizzata ease.

    Potremmo quindi utilizzare ease-out per rallentare lanimazione del treno:

    .train {
      left: 0;
      transition: left 5s ease-out;
      /* same as transition: left 5s cubic-bezier(0, .5, .5, 1); */
    }

    Anche se apparir leggermente diversa.

    Una curva di Bezier pu far eccedere lanimazione dal suo intervallo.

    I punti di controllo nella curva, sono liberi di definire un valore qualsiasi per le coordindate y: sia valori grandi che negativi. Questo si rifletter sulla curva di Bezier che potr essere molto alta o molto bassa, facendo eccedere lanimazione dal suo intervallo normale.

    Nellesempio sotto il codice dellanimazione :

    .train {
      left: 100px;
      transition: left 5s cubic-bezier(.5, -1, .5, 2);
      /* JavaScript imposta left a 400px */
    }

    La propriet left sar animata da 100px a 400px.

    Ma se provate a cliccare il treno, vedrete che:

    • Primo, il treno va indietro: left diventa inferiore a 100px.
    • Poi va in avanti, leggermente oltre i 400px.
    • E successivamente torna nuovamente indietro, fino a 400px.
    Risultato
    style.css
    index.html
    .train {
      position: relative;
      cursor: pointer;
      width: 177px;
      height: 160px;
      left: 100px;
      transition: left 5s cubic-bezier(.5, -1, .5, 2);
    }
    <!doctype html>
    <html>
    
    <head>
      <meta charset="UTF-8">
      <link rel="stylesheet" href="style.css">
    </head>
    
    <body>
    
      <img class="train" src="https://js.cx/clipart/train.gif" onclick="this.style.left='400px'">
    
    </body>
    
    </html>

    Ci che accadde abbastanza ovvio, se andiamo a guardare il grafico della curva di Bezier:

    []

    Abbiamo impostato la coordinata y del secondo punto, sotto lo zero, ed il terzo punto va oltre 1, quindi la curva esce dal quadrante standard. La y eccede quindi lintervallo standard 0..1.

    Come sappiamo, y misura il grado di completezza dellanimazione. Il valore y = 0 corrisponde al valore iniziale della propriet, mentre y = 1 corrisponde al valore finale. Quindi i valori di y<0 spostando la propriet sotto il valore iniziale di left e y>1 oltre il valore finale di left.

    Questa ovviamente una variante pi leggera. Se impostiamo y a valori come -99 e 99 allora il treno eccederebbe lintervallo pi evidentemente.

    Ma come possiamo definire una curva di Bezier per una specifica animazione? Esistono diversi strumenti che ci permettono di farlo. Ad esempio, possiamo utilizzare http://cubic-bezier.com/.

    Steps

    La funzione di temporizzazione steps(number of steps[, start/end]) consente di definire unanimazione in steps (passi).

    Vediamolo in azione su un esempio con cifre.

    Qui abbiamo unelenco di cifre, senza alcuna animazione:

    Risultato
    style.css
    index.html
    #digit {
      border: 1px solid red;
      width: 1.2em;
    }
    
    #stripe {
      display: inline-block;
      font: 32px monospace;
    }
    <!DOCTYPE html>
    <html>
    
    <head>
      <meta charset="utf-8">
      <link rel="stylesheet" href="style.css">
    </head>
    
    <body>
    
      <div id="digit"><div id="stripe">0123456789</div></div>
    
    </body>
    </html>

    Ci che faremo sar far apparire le cifre in modo discreto facendo si che la lista esterna al box rosso sia invisibile, e faremo scorrere la lista a sinistra ad ogni step.

    Dovremo definire 9 step, uno per ogni cifra:

    #stripe.animate  {
      transform: translate(-90%);
      transition: transform 9s steps(9, start);
    }

    In azione:

    Risultato
    style.css
    index.html
    #digit {
      width: .5em;
      overflow: hidden;
      font: 32px monospace;
      cursor: pointer;
    }
    
    #stripe {
      display: inline-block
    }
    
    #stripe.animate {
      transform: translate(-90%);
      transition-property: transform;
      transition-duration: 9s;
      transition-timing-function: steps(9, start);
    }
    <!DOCTYPE html>
    <html>
    
    <head>
      <meta charset="utf-8">
      <link rel="stylesheet" href="style.css">
    </head>
    
    <body>
    
      Click below to animate:
    
      <div id="digit"><div id="stripe">0123456789</div></div>
    
      <script>
        digit.onclick = function() {
          stripe.classList.add('animate');
        }
      </script>
    
    
    </body>
    
    </html>

    Il primo argomento di steps(9, start) il numero di step. La transform verr divisa in 9 parti (10% ad ognuna). Anche lintervallo di tempo sar diviso automaticamente in 9 parti, quindi transition: 9s far durare lanimazione 9 secondi, 1 secondo per ogni cifra.

    Il secondo argomento una delle due parole chiave: start o end.

    La parola chiave start significa che il primo step verr eseguito immediatamente allinizio dellanimazione.

    Possiamo osservarlo durante lanimazione: quando clicchiamo su una cifra cambia ad 1 (il primo step) immediatamente, e successivamente cambier al termine del secondo successivo.

    Il processo progredir in questo modo:

    • 0s -10% (il primo cambiamento allinizio del primo secondo, immediatamente)
    • 1s -20%
    • 8s -80%
    • (lultimo secondo mostra il valore finale).

    In alternativa il valore end star a significare che il cambiamento dovrebbe essere applicato non dallinizio, ma alla fine di ogni secondo.

    Il processo progredir in questo modo:

    • 0s 0
    • 1s -10% (il primo cambiamento alla fine del primo secondo)
    • 2s -20%
    • 9s -90%

    Qui vediamo steps(9, end) in azione (da notare la pausa tra il cambiamento della prima cifra):

    Risultato
    style.css
    index.html
    #digit {
      width: .5em;
      overflow: hidden;
      font: 32px monospace;
      cursor: pointer;
    }
    
    #stripe {
      display: inline-block
    }
    
    #stripe.animate {
      transform: translate(-90%);
      transition-property: transform;
      transition-duration: 9s;
      transition-timing-function: steps(9, end);
    }
    <!DOCTYPE html>
    <html>
    
    <head>
      <meta charset="utf-8">
      <link rel="stylesheet" href="style.css">
    </head>
    
    <body>
    
      Click below to animate:
    
      <div id="digit"><div id="stripe">0123456789</div></div>
    
      <script>
        digit.onclick = function() {
          stripe.classList.add('animate');
        }
      </script>
    
    
    </body>
    
    </html>

    Anche in questo caso esistono delle abbreviazioni:

    • step-start equivale a steps(1, start). Ovvero, lanimazione inizier immediatamente e compier il primo step. Quindi inizier e terminer immediatamente, come se non ci fosse alcuna animazione.
    • step-end equivale a steps(1, end): compie lanimazione in un solo step al termine di transition-duration.

    Questi valori vengono utilizzati raramente. Poich non definiscono delle vere animazioni, ma piuttosto un cambiamento di un solo step.

    Levento transitionend

    Al termine dellanimazione CSS, verr innescato levento transitionend.

    Viene spesso utilizzato per compiere unazione al termine dellanimazione. In questo modo possiamo unire le animazioni.

    Ad esempio, la nave che vediamo nellesempio sotto inizia a navigare quando cliccata, e poi torna indietro, ogni volta si allontana sempre di pi verso destra:

    Lanimazione viene avviata dalla funzione go che viene rieseguita al termine di ogni transizione, invertendo la direzione:

    boat.onclick = function() {
      //...
      let times = 1;
    
      function go() {
        if (times % 2) {
          // naviga verso destra
          boat.classList.remove('back');
          boat.style.marginLeft = 100 * times + 200 + 'px';
        } else {
          // naviga verso sinistra
          boat.classList.add('back');
          boat.style.marginLeft = 100 * times - 200 + 'px';
        }
    
      }
    
      go();
    
      boat.addEventListener('transitionend', function() {
        times++;
        go();
      });
    };

    Loggetto emesso dallevento transitionend possiede un paio di propriet specifiche:

    event.propertyName
    La propriet che ha concluso lanimazione. Pu essere utile se abbiamo definito animazioni per pi propriet.
    event.elapsedTime
    Il tempo (in secondi) impiegato per concludere lanimazione, senza considerare transition-delay.

    Keyframes

    Possiamo unire tra di loro pi animazioni utilizzando la regola CSS @keyframes.

    Tale regola specifica il nome dellanimazione e le modalit: cosa, quando e dove eseguire lanimazione. Successivamente, utilizzando la propriet animation, possiamo attribuire lanimazione allelemento ed eventualmente specificare parametri addizionali.

    Qui vediamo unesempio commentato:

    <div class="progress"></div>
    
    <style>
      @keyframes go-left-right {        /* gli diamo un nome: "go-left-right" */
        from { left: 0px; }             /* anima da sinistra: 0px */
        to { left: calc(100% - 50px); } /* anima verso sinistra: 100%-50px */
      }
    
      .progress {
        animation: go-left-right 3s infinite alternate;
        /* applichiamo l'animazione "go-left-right" all'elemento
           durata 3 secondi
           ripetizioni: infinite
           alterna le direzione ad ogni iterazione
        */
    
        position: relative;
        border: 2px solid green;
        width: 50px;
        height: 20px;
        background: lime;
      }
    </style>

    Potete trovare molti articoli sul tema @keyframes e la specifica dettagliata.

    Probabilmente non avrete bisogno di utilizzare @keyframes spesso, a meno che tutto nel vostro sito sia in costante movimento.

    Riepilogo

    Le animazioni CSS consentono di definire delle animazioni fluide (o meno) su una o pi propriet CSS.

    Sono utili nella maggior parte dei casi in cui dobbiamo definire delle animazioni. Possiamo anche utilizzare JavaScript per definire le animazioni, ed il prossimo capitolo sar infatti dedicato a questo.

    Le limitazioni delle animazioni CSS rispetto a quelle definite utilizzando JavaScript:

    Meriti
    • Le cose semplici sono facili da realizzare.
    • Pi veloci e leggere per la CPU.
    Demeriti
    • Le animazioni JavaScript sono pi flessibili. Possono implementare qualsiasi logica, come un esplosione di un elemento.
    • Non si limitano a cambiamenti di propriet. Con JavaScript possiamo anche creare nuovi elementi da aggiungere allanimazione.

    La maggior parte delle animazioni possono essere implementate con CSS come descritto in questo articolo. Insieme allevento transitionend possiamo eseguire codice al termine dellanimazione, integrandoci perfettamente con lanimazione.

    Nel prossimo articolo vedremo le animazioni con JavaScript, andando a trattare casi pi complessi.

    Esercizi

    importanza: 5

    Definite un animazione che si comporti come quella mostrata nella figura sotto (cliccate lareo):

    • Limmagine si ridimensiona al click da 40x24px a 400x240px (10 volte pi grande).
    • Lanimazione ha una durata di 3 secondi.
    • Al terminte dovrete mostrare: Done!.
    • Durante lanimazione, potrebbero esserci pi click sullaereo. Questi non dovrebbero comprometterne il funzionamento.

    Apri una sandbox per l'esercizio.

    soluzione

    Qui vedete il CSS per animare sia width che height:

    /* classe originale */
    
    #flyjet {
      transition: all 3s;
    }
    
    /* JS aggiunge il ridimensionamento */
    #flyjet.growing {
      width: 400px;
      height: 240px;
    }

    Notate che transitionend si innesca due volte, una per ogni propriet. Quindi senza definire un controllo adeguato, il messaggio verr mostrato due volte.

    Apri la soluzione in una sandbox.

    importanza: 5

    Modificate la soluzione dellesercizio precedente Animate un aereo (CSS) per far s che laereo ecceda le dimensioni originali di 400x240px e successivamente ritorni al suo aspetto originale.

    Cosi come dovrebbe apparire (cliccate sullaereo):

    Prendete la soluzione dellesercizio precedente come punto di partenza.

    soluzione

    Dovete scegliere la giusta curva di Bezier per questa animazione. Deve avere un valore y>1 in qualche punto per far s che laereo ecceda le sue dimensioni originali.

    Ad esempio, potete impostare entrambi i punti di controllo con y>1, come: cubic-bezier(0.25, 1.5, 0.75, 1.5).

    La curva:

    []

    Apri la soluzione in una sandbox.

    importanza: 5

    Create una funzione showCircle(cx, cy, radius) che mostri un cerchio che cresce.

    • cx,cy sono le coordinate del centro del cerchio rispetto alla finestra del browser,
    • radius il raggio del cerchio.

    Cliccate il bottone sotto per vedere come dovrebbe apparire:

    Potente prendere lo stile del cerchio dal codice sorgente, concentrandovi unicamente sullanimazione.

    Apri una sandbox per l'esercizio.

    soluzione

    Nel task Animate il cerchio mostrato un cerchio crescente animato.

    Ora ipotizziamo di non volere solamente un cerchio, ma anche di volere mostrare un messaggio al suo interno. Il messaggio dovrebbe apparire dopo che lanimazione stata completata (il cerchio cresciuto del tutto), altrimenti sarebbe brutto.

    Nella soluzione del task, la funzione showCircle(cx, cy, radius) disegna il cerchio, ma non d modo di monitorare il completamento dellanimazione.

    Aggiungi un argomento callback: showCircle(cx, cy, radius, callback) da chiamare quando lanimazione completa. La callback dovrebbe ricevere il <div> che corrisponde al cerchio come argomento.

    Ecco lesempio:

    showCircle(150, 150, 100, div => {
      div.classList.add('message-ball');
      div.append("Hello, world!");
    });

    Demo:

    Prendi la soluzione task Animate il cerchio come base.

    soluzione
    Mappa del tutorial

    Commenti

    leggi questo prima di lasciare un commento
    • Per qualsiasi suggerimento - per favore, apri una issue su GitHub o una pull request, piuttosto di lasciare un commento.
    • Se non riesci a comprendere quanto scitto nell'articolo ti preghiamo di fornire una spiegazione chiara.
    • Per inserire delle righe di codice utilizza il tag <code>, per molte righe includile nel tag <pre>, per pi di 10 righe utilizza una sandbox (plnkr, jsbin, codepen)

    Web Proxy Viewer  |  New URL  |  Original Page