Canvas HTML: impara a creare forme e grafiche avanzate

Strumenti di base per l’utilizzo delle Canvas HTML

creativecode avatar Giulio Tiseo

20 Ott, 2019

~11min.

In questo tutorial imparerai ad utilizzare i metodi di base che riguardano le canvas HTML. Assimilati i concetti descritti in questo articolo, sarai in grado di creare forme di base attraverso la programmazione e potrai approfondire gli argomenti più complessi.

Canvas HTML: impara a creare forme e grafiche avanzate
Requisiti

Anche se la Canvas è un elemento HTML, è importante che tu conosca anche gli altri linguaggi che compongono una pagina web. In particolare occorre aver fatto un po’ di esperienza con il linguaggio Javascript, perché attraverso di esso potrai popolare le canvas con nuovi oggetti e forme. Se invece non conosci l’HTML, la soluzione puoi trovarla su questo sito, seguendo la Guida base all’HTML.

# Creare animazioni e grafica accattivante su un sito web: da dove cominciare?

Una decina di anni fa sarebbe stato impensabile ottenere la resa che hanno la maggior parte dei siti web che oggi sono presenti fra i featured di awwwards.

Dal punto di vista visual e dell’esperienza utente, è stato fatto un balzo in avanti sorprendente. Grazie alla costante implementazione di nuovi framework che stanno favorendo lo sviluppo di sistemi sempre più sofisticati, immersivi e super accattivanti, oggi le possibilità che ci offrono le moderne tecnologie informatiche sono pressoché infinite.

Posso assicurarti che quando si è impegnati nello sviluppo di siti web e app, lavorare ad alti livelli con la grafica è uno dei momenti più gratificanti in assoluto.

Il problema che però viene evidenziato spesso da chi è alle prime armi è quello di non sapere esattamente da dove cominciare. Un altro dei motivi che porta spesso all’abbandono di questo argomento è causato dal fatto che ci si butta a capofitto su tematiche fin troppo complicate.

In questo tutorial ti parlerò della tecnologia di base per consentirti di approcciare più facilmente al mondo del visual design e del creative coding. Lo scopo è quello di permetterti di approfondire le librerie più interessanti per la gestione di animazioni, controlli di interazione ed effetti visivi.

Da dove si comincia allora? Molto semplice, dal disegno!

# Come è possibile disegnare in una pagina web?

Se intendi progettare un sito accattivante e far sì che le cose prendano vita nelle pagine, non puoi pensare di farlo senza aver prima “imparato a disegnare”.

Attenzione, per imparare a disegnare non intendo dire che tu debba essere necessariamente un illustratore o un’illustratrice. Quello che intendo sottolineare è l’importanza di cercare in te stesso l’approccio tipico dei bambini quando iniziano a disegnare, che consiste nel capire come realizzare le forme di base e tentare man mano di ottenere risultati sempre più complessi. Chiaramente in età infantile molti di noi hanno attraversato questo percorso inconsciamente, ma ora questa filosofia deve essere per te la chiave dell’apprendimento.
Primo obiettivo: riuscire a disegnare forme semplici.

Per cominciare, ciò di cui hai bisogno è un foglio di carta dove poter disegnare. Prima che tu vada alla ricerca del vecchio scatolone impolverato dove conservi gelosamente matite Faber-Castell e colori Giotto, voglio rassicurarti sul fatto che per tua fortuna, almeno i fogli di carta, ti vengono gentilmente offerti dal linguaggio HTML attraverso l’elemento <canvas>.

La specifica HTML5 mette a nostra disposizione una tecnologia piuttosto avanzata che prende il nome di Canvas e che appunto ci consente di disegnare nel browser. Avrai quindi la possibilità, grazie alle canvas html, di realizzare elementi grafici che vanno dalle semplici forme di base fino a veri e propri videogames.

Capire come funziona la canvas html ti spalancherà le porte al mondo delle animazioni per il web, quindi mettiti comodo, apri il tuo editor di testo e prepara una nuova pagina html.

# Predisporre la Canvas HTML

Come ti dicevo nel paragrafo precedente, la prima cosa che devi fare è procurarti un foglio di carta. Puoi ottenerlo direttamente nella tua pagina web creando una nuova canvas HTML in questo modo:

<canvas></canvas>

L’elemento canvas non è ancora pronto fin quando non decidi le dimensioni che dovrà avere.
“Mi serve un A4? un A3?”
Anche se non esistono questi formati sul web, possiamo specificare delle grandezze assolute in pixel. Per dichiarare le dimensioni della canvas HTML, ti basterà applicare gli attributi width e height, così come si fa solitamente per le immagini HTML.

<canvas height="200" width="200"></canvas>

La canvas adesso è stata creata, anche se non vedi nulla. Puoi provare a verificarne l’esistenza attraverso l’ispeziona elemento della developer tools, oppure dichiarando nell’<head> del documento HTML un blocco di stili, così da poter applicare un bordo per evidenziare il perimetro della canvas.

<head>
<!-- title, meta, ecc... -->
  <style>
    canvas {
      border: 1px solid purple;
    }
  </style>
</head>
Canvas HTML con bordo viola
risultato di una canvas HTML ottenuta su codepen.io

Come vedi, hai appena ottenuto un foglio bianco da disegno, evidenziato da un bordo viola.

Adesso che la canvas è pronta, puoi iniziare a disegnare le prime forme di base. Se fosse un foglio di carta avresti bisogno di una matita, nel caso delle canvas HTML lo strumento adatto è il Javascript.

In pratica con il linguaggio Javascript potrai creare nuove forme, programmarle e renderle interattive. Considera il Javascript come il tuo principale strumento di lavoro.

Per poter mettere in relazione il DOM con un nuovo documento Javascript che chiamerò script.js, può essere utile applicare alla canvas HTML un attributo id. L’identificativo mi permette di agganciare comodamente la canvas nello script.js grazie al metodo getElementById().

Ok, procediamo per gradi. Prima di tutto definisci la canvas HTML in questo modo:

<canvas id="canvas" "height="200" width="200"></canvas>

Adesso, collega il documento HTML a un nuovo file Javascript chiamato script.js:

<script src="script.js"></script>

All’interno di script.js, associa la canvas a una nuova variabile puntando al suo id e definisci il “contesto” in cui il tuo disegno deve essere realizzato col metodo getContext().

// In script.js
var ctx = document.getElementById('canvas').getContext('2d');

Cos’è il metodo getContext()? In poche parole è la funzione che ci permette di creare l’ambiente adatto al disegno che intendiamo realizzare.

Si tratta di un disegno che può andar bene in un foglio bidimensionale o deve trovarsi in un ambiente tridimensionale?

In questo tutorial ti parlerò esclusivamente del contesto bidimensionale, per specificare il contesto tridimensionale avrai bisogno di ricorrere al parametro webgl e quindi scrivere: getContext('webgl').

# Disegnare in una canvas HTML bidimensionale

Per realizzare delle forme all’interno della canvas HTML, il contesto che abbiamo scelto nella fase preliminare ti permette di accedere ad una API ricca di metodi e funzioni che puoi sfruttare. Ad esempio puoi provare a creare un quadrato ricorrendo al metodo fillRect() in questo modo:

ctx.fillRect(0, 0, 50, 50);

I parametri che trovi all’interno del metodo fillRect() vanno letti come segue:

“Disegna un quadrilatero le cui coordinate dell’angolo posto in alto a sinistra sono, rispetto alla canvas, x: 0 e y: 0. Il quadrilatero inoltre deve avere una larghezza e un’altezza di 50px.”

Quadrato in una canvas HTML
Quadrato disegnato in una canvas HTML con coordinate 0,0 e dimensione 50px;
ctx.filleRect([coordX], [coordY], [width], [height])

*ATTENZIONE: quando si lavora in grafica, il piano cartesiano è traslato in modo tale che l’origine degli assi corrisponda al punto più in alto a sinistra. Ne consegue che i valori positivi dell’asse delle ordinate (y) si estendano verso il basso, mentre quelli dell’asse delle ascisse (x) verso destra.

Coordinate in Canvas HTML
L’origine del piano cartesiano corrisponde al punto in alto a sinistra, mentre gli assi si estendono positivamente verso destra e verso il basso

Per creare un rettangolo che copra dinamicamente tutta l’area della canvas puoi scrivere:

ctx.fillRect(0, 0, canvas.width, canvas.height);

Qualora le dimensioni del rettangolo dovessero superare quelle della canvas, verrà tagliato e non sarà visibile oltre i limiti imposti dalla canvas stessa.

# Colorare gli oggetti di una canvas HTML

Per colorare gli oggetti che crei all’interno di una canvas HTML puoi utilizzare il metodo fillStyle, che aggiungerà un colore di riempimento diverso a tutti gli oggetti che dichiarerai da quella riga di codice in poi.

var ctx= document.getElementById('canvas').getContext('2d');
ctx.fillStyle = '#EF053D';
var rect = ctx.fillRect(0, 0, 50, 50);

Tutti le grafiche che realizzerai dopo la dichiarazione canvas.fillStyle verranno colorate con #EF053D. Ricorda di dichiarare il colore sempre come stringa, anche nel caso di colori rgb() o rgba()

ctx.fillStyle = 'rgb(239, 5, 61)';

Se intendi creare una nuova forma e vuoi che abbia un colore diverso ti basterà sovrascrivere il valore di fillStyle dell’oggetto canvas, con un altro colore.

ctx.fillStyle = '#EF053D';
var rect = ctx.fillRect(0, 0, 50, 50);
ctx.fillStyle = '#008f95';
var second_rect = ctx.fillRect(60, 0, 50, 50);
Due quadrati colorati in modo diverso con FillStyle
Per colorare due quadrati con colori diversi basta sovrascrivere il valore di fillStyle nella canvas HTML

Prova a spostare a tuo piacimento i quadrati nella canvas in modo da acquisire dimestichezza. Se non hai ancora ben chiaro il modo corretto per spostare gli oggetti nella canvas, osserva l’esempio qui sotto e prova a interpretarlo abbozzando in scala uno schizzo su carta.

var ctx = document.getElementById('canvas').getContext('2d');
ctx.fillStyle = 'rgba(239,6,61,0.8)';
var rect = ctx.fillRect(75, 75, 50, 50);
ctx.fillStyle = 'rgba(0, 142,149,0.5)';
var second_rect = ctx.fillRect(50, 55, 50, 50);

Il risultato del codice in alto corrisponde a due quadrati sovrapposti, con un’opacità di 0.8. Se ti è tutto chiaro, continua la lettura, altrimenti leggi con maggiore attenzione il paragrafo in cui ti ho parlato delle coordinate della canvas HTML.

Due quadrati che si sovrappongono in una canvas HTML

# Disegnare circonferenze in una canvas HTML

La specifica HTML5 non fornisce per le circonferenze un metodo già pronto come accade per il fillRect() nel caso del rettangolo. Per creare una circonferenza occorre ingegnarsi un po’ con il metodo arc() e fare quindi in modo di creare una curva che ruoti di 360 gradi. Ops, ho detto “360 gradi“, scusa… volevo dire 2PI (pi greco, ricordi? Le scuole superiori… la trigonometria…AH DANNAZIONE!).

Quando siamo alle prese con il metodo arc(), occorre fare mente locale prima di capire esattamente come creare una circonferenza o lavorare col metodo arc(). Il dover ragionare in radianti e non in gradi può essere frustrante all’inizio, ma sta tranquillo… non è niente di troppo complicato.

 

Prima di entrare nel vivo del metodo arc(), hai bisogno di inizializzare nella canvas un blocco di codice all’interno del quale potrai definire la circonferenza.

Che significa inizializzare un blocco di codice? arc() è un metodo piuttosto versatile e più flessibile di fillRect(); ciò significa che attraverso di esso potrai creare tantissime forme. Proprio per questo motivo il codice che definisce i parametri di tale forma, vanno racchiusi all’interno di un blocco di dichiarazioni delimitate dai metodi beginPath() e closePath().

canvas.beginPath()
// Qui creerai la circonferenza
canvas.closePath()

Per creare una circonferenza col metodo arc() devi prendere in considerazione una dichiarazione strutturata in questo modo:

ctx.arc([coordCentroX], [coordCentroY], [raggio], [angoloDiPartenza], [angoloDiChiusura])

Analizziamo ciascun parametro per capire esattamente in cosa consiste il metodo arc():

  1. Coordinata X del punto centrale della curva;
  2. Coordinata Y del punto centrale della curva;
  3. Raggio di apertura della curva rispetto al punto centrale;
  4. Angolo di partenza della curva dichiarato in radianti;
  5. Angolo di chiusura della curva dichiarato in radianti;

Considerata una canvas HTML di dimensioni 200×200, se volessimo creare una circonferenza iscritta nella canvas, dovremo scrivere:

ctx.arc(100, 100, 100, [angoloDiPartenza], [angoloDiChiusura])

A questo punto, prima di definire l’angolo di partenza e l’angolo di chiusura della circonferenza devi un attimo rispolverare qualche piccola nozione trigonometrica di base.

Considerato che l’angolo piatto (180 gradi) corrisponde a PI, ne consegue che l’angolo giro (360 gradi) sia uguale a 2 * PI (ovvero: 2 * 180 gradi).

Perciò, se l’angolo di partenza della circonferenza è 0, quello di chiusura sarà 360 gradi, che in radianti corrisponde appunto a 2 * PI.

Javascript mette a disposizione il valore della costante PI nell’oggetto Math, quindi puoi scrivere:

ctx.arc(100, 100, 100, 0, 2 * Math.PI)

In questo modo hai creato la circonferenza, anche se non vedi alcun cambiamento nella canvas. Questo accade perché, essendo semplicemente una curva, non è così scontato che debba avere un colore di riempimento o una traccia di contorno. Per aggiungere queste caratteristiche al path appena creato ricorriamo ai metodi fill() per il riempimento e stroke() per la traccia.

ctx.beginPath();
ctx.fillStyle = 'rgba(0, 142,149, 1)';
ctx.arc(100, 100, 100, 0, 2 * Math.PI);
ctx.fill();
ctx.stroke();
ctx.closePath();
Circonferenza in canvas HTML
Per ottenere una circonferenza in una canvas basta scrivere [context].arc([centroX], [centroY], [raggio], 0, 2 * PI)

Ottimo, la circonferenza inscritta alla canvas è stata creata e non è per niente male. Adesso proviamo a fare un po’ di pratica con il metodo arc() per prendere confidenza con i radianti.

Abbiamo detto che l’angolo piatto corrisponde a PI, mentre l’angolo giro corrisponde a 2 * PI. Riesci a capire come ottenere nella canvas un risultato simile a questo?

Creare mezza circonferenza con senso orario in canvas HTML

Osservando la canvas dovresti aver capito che ad essere variato prima di tutto è il punto di partenza della circonferenza. Se non capisci di cosa sto parlando, osserva il grafico qui sotto che ti mostra la divisione dell’angolo giro in quattro parti uguali.

Suddivisione della circonferenza in quattro parti uguali
0deg = 0 * PI | 90 deg = 0.5* PI | 180 deg = 1 * PI | 270 deg = 1.5 * PI

Mi raccomando di fare attenzione al grafico in alto! In questo esempio sto evidenziando nuovamente che gli assi cartesiani sono rovesciati rispetto alla convenzione che utilizzavamo a scuola: i 90 gradi sono rappresentati in basso (0.5 PI), mentre i 270 gradi (1.5 PI) sono quelli in alto!

Ne consegue che per ottenere la mezza circonferenza vista nell’esempio precedente, il punto di partenza corrisponderà a 1.5 * PI, mentre la chiusura a 0.5 * PI.

ctx.arc(100, 100, 100, 1.5 * Math.PI, 0.5 * Math.PI);

In questo momento sei legittimato a protestare e dirmi: “Chi lo ha detto ad arc() di ruotare in senso orario?! “. Hai ragione, non ti ho ancora parlato del sesto parametro opzionale di arc() ovvero quello che ti permette di specificare il senso di rotazione.

ctx.arc([coordCentroX], [coordCentroY], [raggio], [angoloDiPartenza], [angoloDiChiusura], [opz: sensoDiRotazione])

Questo parametro opzionale è un valore booleano (true/false): con false (che è il valore impostato di default) applichiamo ad arc() una rotazione oraria, mentre con true una rotazione antioraria. Scrivendo quindi…

ctx.beginPath();
ctx.fillStyle = 'rgba(0, 142,149, 1)';
ctx.arc(100, 100, 100, 1.5 * Math.PI, 0.5 * Math.PI, true);
ctx.fill();
ctx.stroke();
ctx.closePath();

…otterrai un oggetto speculare all’esempio visto in precendenza perché ho semplicemente invertito il senso di rotazione da orario ad antiorario.

Creare mezza circonferenza con senso antiorario in canvas HTML

Creare circonferenze multiple: creiamo una Sfera Poké!

Così come abbiamo visto per fillRect() è possibile realizzare diverse circonferenze nella stessa canvas, ma devi fare attenzione a una cosa! Per creare diverse forme con il metodo arc() devi ricordarti di chiudere un path e aprirne uno nuovo per ogni oggetto che creerai.

var ctx = document.getElementById('canvas').getContext('2d');

ctx.beginPath();
ctx.fillStyle = '#EF053D';
ctx.arc(100, 100, 100, 0, 1 * Math.PI, true);
ctx.fill();
ctx.closePath();

ctx.beginPath();
ctx.fillStyle = 'rgba(24,30,40,0.1)';
ctx.arc(100, 100, 100, 0, 1 * Math.PI);
ctx.fill();
ctx.closePath();

ctx.beginPath();
ctx.fillStyle = 'rgba(24,30,40,0.05)';
ctx.arc(100, 100, 100, 1.5 * Math.PI, 0.5 * Math.PI);
ctx.fill();
ctx.closePath();

ctx.beginPath();
ctx.fillStyle = '#FCFCFC';
ctx.arc(100, 100, 32, 0, 2 * Math.PI, true);
ctx.fill();
ctx.stroke();
ctx.closePath();

ctx.beginPath();
ctx.arc(100, 100, 25, 0, 2 * Math.PI, true);
ctx.stroke();
ctx.closePath();

…risultato:

Prototipo di sfera poke realizzata con canvas HTML
Prototipo di una sfera poké realizzata in una canvas HTML

Già che ci siamo, proviamo a migliorare questo esempio con i metodi lineWidth, strokeStyle() e moveTo() / lineTo(), poi ti spiegherò il loro scopo.

var ctx = document.getElementById('canvas').getContext('2d');

ctx.beginPath();
ctx.fillStyle = '#EF053D';
ctx.arc(100, 100, 100, 0, 1 * Math.PI, true);
ctx.fill();
ctx.closePath();

ctx.beginPath();
ctx.fillStyle = 'rgba(24,30,40,0.1)';
ctx.arc(100, 100, 100, 0, 1 * Math.PI);
ctx.fill();
ctx.closePath();

ctx.beginPath();
ctx.fillStyle = 'rgba(24,30,40,0.05)';
ctx.arc(100, 100, 100, 1.5 * Math.PI, 0.5 * Math.PI);
ctx.fill();
ctx.closePath();

ctx.beginPath();
ctx.moveTo(0, 100);
ctx.lineTo(200, 100);
ctx.lineWidth = 8;
ctx.stroke();
ctx.closePath();

ctx.beginPath();
ctx.fillStyle = '#FCFCFC';
ctx.arc(100, 100, 32, 0, 2 * Math.PI, true);
ctx.fill();
ctx.lineWidth = 8;
ctx.stroke();
ctx.closePath();

ctx.beginPath();
ctx.fillStyle = '#fff';
ctx.arc(100, 100, 22, 0, 2 * Math.PI, true);
ctx.fill();
ctx.lineWidth = 2;
ctx.strokeStyle = 'lightgray';
ctx.stroke();
ctx.closePath();

Adesso va molto meglio!

Sfera Poké in canvas HTML

Vediamo nel dettaglio le modifiche apportate alla canvas:

  • Creazione di una linea attraverso i metodi moveTo() e lineTo(): in moveTo() vai ad impostare le coordinate del punto di partenza della linea, mentre con lineTo() dichiari il punto finale.
  • Aumentare lo spessore del bordo con lineWidth: accetta come valore numeri interi che indicano la quantità di pixel da usare per lo spessore della traccia.
  • Cambiare il colore della traccia con strokeStyle: che accetta qualsiasi colore in formato HEX, rgb, rgba o i classici color preset dell’HTML.

Come vedi, con un po’ di pratica è stato possibile creare qualcosa di più interessante di un semplice quadrato colorato.

Ovviamente questo è solo l’inizio! La canvas HTML offre un’infinità di altre possibilità che non mancherò di mostrarti nei prossimi tutorial. Nel frattempo, puoi sbizzarrirti e iniziare a sperimentare con questa straordinaria API approfondendo l’argomento anche sull’eccellente documentazione stilata da mozilla.

Buon creative coding e alla prossima!

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *