Nello standard HTML5, viene introdotto l'elemento canvas per lavorare con la grafica raster. L'approccio all'elaborazione grafica tramite JavaScript basato su questo elemento è definito dalle specifiche W3C relative al contesto 2D. Allo stato attuale, infatti, le specifiche prevedono la possibilità di generare soltanto grafica bidimensionale su un elemento <canvas>
.
Lo stesso elemento, tuttavia, viene utilizzato per la generazione di grafica 3D sfruttando WebGL, le cui specifiche, pur non essendo standardizzate dal W3C, sono ormai largamente supportate dai browser.
Tramite le API del contesto bidimensionale possiamo disegnare e colorare forme geometriche, creare gradienti, copiare immagini e, più in generale, manipolare pixel.
A differenza della grafica vettoriale SVG, infatti, l'approccio basato su canvas
consente la gestione di grafica bitmap, con tutti i possibili vantaggi e svantaggi che questa comporta.
Ma vediamo come possiamo sfruttare queste API per creare dei semplici elementi grafici.
Disegnare su Canvas
Innanzitutto puntualizziamo il concetto che un canvas è letteralmente una tela su cui possiamo disegnare e colorare ed è individuata su una pagina HTML dall'elemento <canvas>
:
<canvas id="myCanvas"></canvas>
Se non indichiamo delle dimensioni specifiche tramite gli attributi width
e height
, le dimensioni predefinite sono fissate in 300 pixel per l'ampiezza e 150 per l'altezza, indipendentemente dal browser.
La prima cosa da fare per poter lavorare sulla nostra tela è acquisire il contesto di lavoro tramite il metodo getContext()
dell'oggetto canvas
:
var myCanvas = document.getElementById("myCanvas");
var context = myCanvas.getContext("2d");
Una volta acquisito il contesto, possiamo utilizzare un ampio numero di metodi e proprietà per creare i nostri elementi grafici. Ad esempio, il seguente codice disegna un cerchio del tutto identico a quello che abbiamo creato con SVG:
context.beginPath();
context.arc(100, 100, 50, 0, 2 * Math.PI);
context.fillStyle = "#00ff00";
context.fill();
context.strokeStyle = "#000000";
context.stroke();
Il metodo beginPath() consente di avviare il disegno di un nuovo elemento. Possiamo immaginare che l'invocazione di questo metodo appoggi la punta del pennello sulla tela pronto per iniziare il disegno o la colorazione.
Per disegnare il cerchio sfruttiamo il metodo arc(), il cui compito è quello di disegnare un arco, fornendo come parametri le coordinate del centro, la dimensione del raggio, l'angolo iniziale e l'angolo finale dell'arco. Nel nostro caso abbiamo indicato come arco iniziale l'arco di zero radianti e come angolo finale l'angolo giro (2 pi-greco).
Abbiamo quindi indicato il colore per il riempimento e l'abbiamo applicato tramite il metodo fill() ed il colore del bordo applicandolo tramite stroke().
Animazioni su Canvas
Per creare l'effetto di animazione analogo a quello che abbiamo realizzato sfruttando SVG, procediamo con il parametrizzare le coordinate del cerchio e creare una funzione che ha il compito di disegnarlo:
var x = 100;
var y = 100;
function drawCircle(x, y) {
context.beginPath();
context.arc(x, y, 50, 0, 2 * Math.PI);
context.fillStyle = "#00ff00";
context.fill();
context.strokeStyle = "#000000";
context.stroke();
}
Quindi definiamo una funzione che sposta il cerchio all'interno del canvas:
function animate() {
x = x + 2;
if (x > myCanvas.width) x = 20;
context.clearRect(0, 0, myCanvas.width, myCanvas.height);
drawCircle(x, y);
}
Notiamo come per spostare il cerchio abbiamo cancellato l'intera superficie del canvas tramite il metodo clearRect()
e ridisegnato la figura geometrica cambiando leggermente la coordinata x
.
A questo punto non ci resta che attivare l'animazione tramite un timer:
var timerId;
function startAnimation() {
if( timerId == null) {
timerId = setInterval(animate, 20);
}
}
startAnimation();
L'approccio alla gestione della grafica basato su canvas ci consente non solo di disegnare a partire da una tela vuota, ma di modificare immagini esistenti, di copiarle ed esportare il risultato delle nostre elaborazioni in un formato di tipo bitmap.
Caricare un'immagine in Canvas
Per importare un'immagine esistente all'interno di un canvas, possiamo procedere come mostrato dal seguente codice:
var img = new Image();
img.onload = function() {
context.drawImage(img, 0, 0);
};
img.src = "immagine.jpg";
Abbiamo creato un oggetto di tipo immagine inserendolo nel nostro canvas tramite il metodo drawImage()
. Questo metodo prevede come parametri l'immagine e le coordinate all'interno del canvas in cui visualizzarla.
È importante inserire l'immagine nel canvas dopo che questa sia stata effettivamente caricata nel DOM. Per questo motivo il metodo drawImage()
viene invocato in corrispondenza dell'evento load
.
Una volta nel canvas, possiamo manipolare l'immagine mediante tutte le funzionalità previste dalle API. Possiamo anche fare una copia in un formato diverso dall'originale sfruttando il metodo toDataUrl() dell'elemento <canvas>
:
var imgElement = document.createElement("img");
var myCanvas = document.getElementById("myCanvas");
imgElement.src = myCanvas.toDataUrl("image/png");
document.body.appendChild(imgElement);
Nell'esempio abbiamo creato un elemento <img>
ed abbiamo associato al suo attributo src
l'immagine del canvas myCanvas
in formato png
.
È opportuno evidenziare che il metodo toDataUrl()
è un metodo dell'elemento <canvas>
e non del contesto. Infatti, in questo caso accediamo all'insieme dei pixel contenuti nel canvas
senza alcuna intenzione di modificarli.
Link utili