L’elemento <canvas> di HTML5 ha aperto possibilità straordinarie per la creazione di grafica, animazioni e visualizzazioni interattive direttamente nel browser, senza la necessità di plugin esterni. Utilizzato in combinazione con JavaScript, Canvas permette di disegnare forme, renderizzare testo, manipolare immagini e creare animazioni fluide. In questa guida esploreremo le fondamenta del disegno su Canvas e le tecniche per creare contenuti grafici coinvolgenti.
L’Elemento Canvas e il Contesto di Rendering
L’elemento <canvas> è essenzialmente un’area rettangolare nel documento HTML che funge da superficie di disegno. Di per sé, il tag canvas non mostra nulla: tutto il disegno avviene tramite JavaScript, utilizzando un oggetto chiamato “contesto di rendering” che fornisce i metodi e le proprietà necessarie per disegnare.
Le dimensioni del canvas si definiscono tramite gli attributi width e height direttamente sull’elemento HTML, non tramite CSS. Questa distinzione è importante: gli attributi HTML definiscono la risoluzione reale della superficie di disegno, mentre il CSS controlla solo le dimensioni di visualizzazione. Se le due non corrispondono, il contenuto apparirà sfocato o distorto. La dimensione predefinita è 300×150 pixel.
Per ottenere il contesto di rendering 2D, si utilizza il metodo getContext(‘2d’) sull’elemento canvas. Questo oggetto contesto è il punto di accesso a tutte le operazioni di disegno. Esiste anche un contesto WebGL per la grafica 3D, ma per la maggior parte delle applicazioni il contesto 2D è più che sufficiente.
È buona pratica includere un contenuto testuale di fallback tra i tag di apertura e chiusura di <canvas>, che verrà visualizzato dai browser che non supportano l’elemento. Sebbene oggi il supporto sia universale, il fallback migliora l’accessibilità per le tecnologie assistive che non possono interpretare il contenuto grafico.
Disegnare Forme: Rettangoli, Cerchi e Linee
Il contesto 2D di Canvas offre metodi diretti per disegnare rettangoli e un sistema basato su percorsi (paths) per tutte le altre forme. Per i rettangoli, i metodi principali sono: fillRect(x, y, width, height) per un rettangolo pieno, strokeRect(x, y, width, height) per un rettangolo con solo bordo, e clearRect(x, y, width, height) per cancellare un’area rettangolare.
Per disegnare cerchi, archi e forme complesse, si utilizza il sistema dei percorsi. Un percorso si inizia con beginPath(), si definisce con una serie di comandi di disegno, e si finalizza con fill() per riempirlo o stroke() per tracciarne il contorno. Il metodo arc(x, y, raggio, angoloInizio, angoloFine) disegna un arco di cerchio, dove gli angoli sono espressi in radianti. Un cerchio completo va da 0 a 2*Math.PI.
Per le linee, si usa moveTo(x, y) per posizionare il cursore e lineTo(x, y) per tracciare una linea dal punto corrente al nuovo punto. La proprietà lineWidth controlla lo spessore della linea, lineCap definisce la forma delle estremità (“butt”, “round”, “square”) e lineJoin controlla la giunzione tra segmenti (“round”, “bevel”, “miter”). Queste proprietà permettono un controllo fine sull’aspetto delle linee.
Le curve di Bézier permettono di creare forme organiche e fluide. Il metodo quadraticCurveTo(cpx, cpy, x, y) disegna una curva con un punto di controllo, mentre bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y) utilizza due punti di controllo per curve più complesse. Con queste primitive è possibile creare qualsiasi forma geometrica.
Colori, Gradienti e Pattern
Il canvas supporta una vasta gamma di opzioni per colorare le forme. Le proprietà fillStyle e strokeStyle accettano stringhe di colore CSS (nomi, hex, rgb, rgba, hsl, hsla), permettendo anche la trasparenza tramite il canale alfa. La proprietà globalAlpha imposta la trasparenza globale per tutte le operazioni di disegno successive.
I gradienti lineari si creano con createLinearGradient(x0, y0, x1, y1), che definisce la direzione del gradiente attraverso due punti. Si aggiungono poi i colori con addColorStop(posizione, colore), dove la posizione è un valore tra 0 e 1. I gradienti radiali si creano con createRadialGradient(x0, y0, r0, x1, y1, r1), che definisce due cerchi tra cui si sviluppa il gradiente.
I pattern permettono di riempire aree con immagini ripetute. Si creano con createPattern(immagine, ripetizione), dove la ripetizione può essere “repeat”, “repeat-x”, “repeat-y” o “no-repeat”. L’immagine sorgente può essere un elemento Image, un altro canvas o un elemento video, offrendo grande flessibilità creativa.
Le ombre si controllano tramite quattro proprietà: shadowColor per il colore, shadowBlur per la sfocatura, shadowOffsetX e shadowOffsetY per lo spostamento. Le ombre vengono applicate a tutte le operazioni di disegno successive, inclusi rettangoli, percorsi e testo, aggiungendo profondità alle composizioni grafiche.
Testo e Immagini su Canvas
Il canvas permette di renderizzare testo utilizzando i metodi fillText(testo, x, y) e strokeText(testo, x, y). La proprietà font accetta la stessa sintassi della proprietà CSS font (ad esempio “bold 24px Arial”). Le proprietà textAlign (“left”, “center”, “right”, “start”, “end”) e textBaseline (“top”, “middle”, “bottom”, “alphabetic”) controllano l’allineamento del testo rispetto alle coordinate specificate.
Per misurare le dimensioni del testo prima di disegnarlo, il metodo measureText(testo) restituisce un oggetto TextMetrics con la larghezza del testo, utile per centrare il testo o creare layout testuali complessi.
Il disegno di immagini su canvas avviene tramite il metodo drawImage(), che accetta tre varianti: la versione base drawImage(img, x, y) disegna l’immagine alle coordinate specificate; drawImage(img, x, y, width, height) la ridimensiona; e drawImage(img, sx, sy, sw, sh, dx, dy, dw, dh) permette di ritagliare una porzione dell’immagine sorgente e disegnarla ridimensionata. Quest’ultima versione è particolarmente utile per gli sprite sheet nelle animazioni e nei giochi.
Animazioni con requestAnimationFrame
Le animazioni su canvas seguono un pattern fondamentale: cancellare il canvas, aggiornare lo stato degli oggetti e ridisegnare tutto in un ciclo continuo. La funzione requestAnimationFrame(callback) è il metodo standard per creare questo ciclo di animazione, sincronizzato con il refresh rate del monitor (tipicamente 60fps).
A differenza di setInterval o setTimeout, requestAnimationFrame viene automaticamente sospeso quando la scheda del browser non è visibile, risparmiando risorse di CPU e batteria. Inoltre, il browser ottimizza internamente il timing per garantire animazioni fluide senza tearing o stuttering.
Il pattern tipico di un’animazione prevede una funzione che viene chiamata ricorsivamente: all’interno della funzione si cancella il canvas con clearRect(), si aggiornano le posizioni e gli stati degli oggetti animati, si ridisegnano tutti gli elementi e infine si richiama requestAnimationFrame con la stessa funzione come callback. Per animazioni time-based (indipendenti dal frame rate), si utilizza il parametro timestamp fornito automaticamente dalla callback.
Le ottimizzazioni comuni per le animazioni includono: ridisegnare solo le aree modificate anziché l’intero canvas, utilizzare un canvas fuori schermo (offscreen canvas) per operazioni di pre-rendering, e sfruttare le trasformazioni del canvas (translate, rotate, scale) per evitare calcoli matematici complessi nelle coordinate.
Canvas vs SVG: Quando Usare Cosa
La scelta tra Canvas e SVG dipende dal tipo di applicazione. Il Canvas è basato su pixel (raster) ed è più adatto per: animazioni complesse con molti elementi in movimento, giochi, elaborazione di immagini in tempo reale, visualizzazioni di dati con migliaia di punti, e qualsiasi scenario in cui le performance sono critiche.
SVG è basato su vettori ed è preferibile per: grafici e diagrammi interattivi, icone e illustrazioni scalabili, interfacce utente con elementi cliccabili, animazioni semplici con pochi elementi, e contenuti che devono mantenere la qualità a qualsiasi dimensione. Per una guida dettagliata sulla grafica SVG, consulta il nostro articolo su SVG in HTML.
In pratica, Canvas eccelle quando il numero di elementi è elevato e le interazioni dirette con singoli elementi non sono necessarie, mentre SVG è superiore quando ogni elemento grafico deve essere indipendentemente manipolabile e accessibile. In alcuni casi, combinare entrambe le tecnologie nella stessa pagina è la soluzione ottimale.
Hai bisogno di aiuto con la creazione di grafica e animazioni per il tuo sito web? G Tech Group offre servizi di sviluppo web professionale e consulenza tecnica. Contattaci a su*****@********up.it o via WhatsApp al 0465 84 62 45.