Disegno su Canvas
Impara a disegnare sull'HTML canvas con JavaScript: rettangoli, contorni, percorsi, linee, cerchi e archi, con esempi di codice eseguibili.
L'elemento <canvas> è semplicemente una superficie di disegno vuota e trasparente. Da solo non mostra nulla — non è possibile disegnare su di esso con HTML o CSS. Tutto il disegno su un canvas viene eseguito con JavaScript, attraverso un oggetto chiamato contesto di rendering. Questa pagina illustra passo dopo passo le operazioni di disegno 2D fondamentali: riempire rettangoli, tracciare contorni, disegnare percorsi a forma libera e disegnare cerchi e archi.
Se non hai ancora creato un elemento <canvas>, inizia con il tag HTML <canvas> e l'introduzione a Canvas.
Il sistema di coordinate del canvas
Ogni metodo di disegno utilizza coordinate in pixel. La griglia del canvas ha la sua origine (0, 0) nell'angolo in alto a sinistra. L'asse x cresce verso destra e l'asse y cresce verso il basso (nota che y aumenta man mano che ci si sposta verso il basso, al contrario di un grafico matematico). Quindi il punto (0, 0) è il pixel in alto a sinistra, e (width, height) è l'angolo in basso a destra.
Per un approfondimento sulla griglia, vedi Coordinate del canvas.
1. Trovare l'elemento canvas
Per prima cosa, ottieni un riferimento all'elemento <canvas> nel DOM con getElementById():
const canvas = document.getElementById("canvas");2. Ottenere il contesto di rendering 2D
Chiama il metodo getContext() per ottenere un contesto di disegno. Passando "2d" si ottiene un oggetto CanvasRenderingContext2D, che contiene tutte le proprietà e i metodi usati per disegnare:
const ctx = canvas.getContext("2d");La variabile ctx (abbreviazione di "context") è quella su cui si chiamano tutti i comandi di disegno.
getContext() restituisce null se il browser non può fornire il contesto richiesto (ad esempio, se "2d" è scritto in modo errato, o se l'elemento non è effettivamente un <canvas>). È buona pratica gestire questo caso prima di disegnare, così un contesto mancante non genera errori silenziosi sulla riga successiva:
const ctx = canvas.getContext("2d");
if (!ctx) return; // bail out if the 2D context is unavailable; only valid inside a functionIn uno <script> inline semplice (che non è il corpo di una funzione), racchiudi il disegno in if (ctx) { ... } come fanno gli esempi seguenti.
3. Disegnare un rettangolo pieno
La proprietà fillStyle imposta il colore usato per riempire le forme. Può essere qualsiasi colore CSS, un pattern o un gradiente:
ctx.fillStyle = "#1c87c9";Poi fillRect(x, y, width, height) disegna un rettangolo pieno. I primi due parametri sono le coordinate x e y dell'angolo in alto a sinistra, seguite da larghezza e altezza in pixel:
ctx.fillRect(0, 0, 230, 130);Esempio di disegno di un rettangolo pieno:
<!DOCTYPE html>
<html>
<head>
<title>Title of the document</title>
</head>
<body>
<canvas id="canvas" width="250" height="150" role="img"
aria-label="A blue filled rectangle" style="border:1px solid #dddddd;">
Your browser does not support the canvas element.
</canvas>
<script>
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
if (ctx) {
// only draw when the 2D context is available
ctx.fillStyle = "#1c87c9";
ctx.fillRect(0, 0, 230, 130);
}
</script>
</body>
</html>Rendere il canvas accessibile
Tutto ciò che disegni su un canvas è solo pixel — non ha struttura, quindi gli screen reader non possono leggerlo. Non c'è nulla da annunciare e gli utenti che usano la tastiera non possono accedere a nulla al suo interno. Fornisci alla tecnologia assistiva un equivalente testuale in due modi:
- Il contenuto di fallback va tra i tag
<canvas>. I browser che renderizzano il canvas lo ignorano; la tecnologia assistiva (e i browser molto vecchi) lo usano al suo posto. Metti qui una descrizione significativa, non "il tuo browser non supporta canvas." role="img"insieme adaria-labeldescrive il disegno completato come una singola immagine, allo stesso modo in cui il testoaltdescrive un<img>.
<canvas id="chart" width="250" height="150" role="img"
aria-label="Bar chart: sales doubled from Q1 to Q2.">
A bar chart showing sales doubling from Q1 to Q2.
</canvas>Per qualsiasi elemento interattivo (aree cliccabili, controlli), fornisci anche elementi DOM reali e focalizzabili — il canvas da solo non è accessibile da tastiera.
Contorno senza riempimento
A volte si vuole solo il contorno di una forma invece di un riempimento solido. Usa la proprietà strokeStyle per impostare il colore del contorno e strokeRect(x, y, width, height) per disegnare un rettangolo non riempito. La proprietà lineWidth controlla lo spessore del contorno:
<!DOCTYPE html>
<html>
<head>
<title>Title of the document</title>
</head>
<body>
<canvas id="canvas" width="250" height="150" role="img"
aria-label="A blue rectangular outline" style="border:1px solid #dddddd;">
A rectangle drawn as an outline.
</canvas>
<script>
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
if (ctx) {
ctx.strokeStyle = "#1c87c9";
ctx.lineWidth = 4;
ctx.strokeRect(20, 20, 200, 100);
}
</script>
</body>
</html>Cancellare una parte del canvas
clearRect(x, y, width, height) cancella il rettangolo specificato, rendendolo nuovamente completamente trasparente. Viene comunemente usato per pulire l'intero canvas prima di ridisegnare (ad esempio, a ogni frame di un'animazione):
// Erase everything on a 250 × 150 canvas
ctx.clearRect(0, 0, 250, 150);Nell'esempio seguente vengono disegnati due rettangoli blu, e poi clearRect() ritaglia un buco trasparente nel mezzo del canvas — nota che il rettangolo di destra viene parzialmente cancellato:
<!DOCTYPE html>
<html>
<head>
<title>Title of the document</title>
</head>
<body>
<canvas id="canvas" width="250" height="150" role="img"
aria-label="Two blue squares with a cleared rectangle cut out of the middle"
style="border:1px solid #dddddd;">
Two filled squares with a cleared region.
</canvas>
<script>
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
if (ctx) {
ctx.fillStyle = "#1c87c9";
ctx.fillRect(20, 20, 100, 100);
ctx.fillRect(130, 20, 100, 100);
ctx.clearRect(90, 50, 70, 50); // erase a rectangle across both
}
</script>
</body>
</html>Disegnare percorsi (linee e forme personalizzate)
I rettangoli sono comodi, ma la maggior parte dei disegni usa i percorsi — sequenze di punti collegati da linee o curve. Un percorso viene costruito con un insieme ristretto di metodi e non è visibile finché non si chiama stroke() (per disegnare il contorno) o fill() (per riempire l'area racchiusa).
| Metodo | Cosa fa |
|---|---|
beginPath() | Avvia un nuovo percorso vuoto. |
moveTo(x, y) | Sposta il "pennino" in (x, y) senza disegnare. |
lineTo(x, y) | Aggiunge una linea retta dal punto corrente a (x, y). |
closePath() | Disegna una linea di ritorno al punto iniziale del percorso. |
stroke() | Renderizza il percorso come contorno. |
fill() | Riempie l'area racchiusa dal percorso. |
Inizia sempre con beginPath()
beginPath() cancella l'elenco di punti che il contesto sta attualmente tracciando e avvia un nuovo percorso. Questo è importante perché il canvas ricorda ogni sotto-percorso finché non viene azzerato. Se disegni una forma e poi aggiungi punti per una seconda forma senza chiamare beginPath(), i vecchi punti sono ancora nel percorso — quindi il successivo stroke() o fill() ridisegna anche la prima forma, spesso con il nuovo colore e spessore di linea. Il risultato è che le forme "sconfinano" l'una nell'altra.
Regola pratica: chiama beginPath() prima di ogni nuova forma. Ogni esempio qui sotto inizia in questo modo.
Esempio: una singola linea
Per disegnare una linea, inizia un percorso, spostati nel punto di partenza, traccia una linea fino al punto finale e poi applicale il contorno:
<!DOCTYPE html>
<html>
<head>
<title>Title of the document</title>
</head>
<body>
<canvas id="canvas" width="250" height="150" role="img"
aria-label="A diagonal blue line" style="border:1px solid #dddddd;">
A diagonal line drawn across the canvas.
</canvas>
<script>
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
if (ctx) {
ctx.beginPath();
ctx.moveTo(20, 20); // start point (x, y)
ctx.lineTo(220, 120); // end point (x, y)
ctx.lineWidth = 3;
ctx.strokeStyle = "#1c87c9";
ctx.stroke(); // make the line visible
}
</script>
</body>
</html>Esempio: un triangolo
Concatenare più chiamate a lineTo() crea una forma a più lati. closePath() collega l'ultimo punto al primo, e fill() riempie l'area racchiusa:
<!DOCTYPE html>
<html>
<head>
<title>Title of the document</title>
</head>
<body>
<canvas id="canvas" width="250" height="150" role="img"
aria-label="A filled green triangle" style="border:1px solid #dddddd;">
A filled green triangle.
</canvas>
<script>
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
if (ctx) {
ctx.beginPath();
ctx.moveTo(125, 20); // top vertex
ctx.lineTo(220, 130); // bottom-right vertex
ctx.lineTo(30, 130); // bottom-left vertex
ctx.closePath(); // back to the top vertex
ctx.fillStyle = "#8ebf42";
ctx.fill();
}
</script>
</body>
</html>Disegnare cerchi e archi
Il metodo arc() disegna cerchi e segmenti curvi:
ctx.arc(x, y, radius, startAngle, endAngle, counterclockwise);x,y— le coordinate del centro dell'arco.radius— il raggio in pixel.startAngle,endAngle— gli angoli di inizio e fine in radianti (non in gradi). L'angolo0punta lungo l'asse x positivo — dritto verso destra, la direzione delle ore 3 — e per default gli angoli aumentano in senso orario (perché l'asse y del canvas cresce verso il basso). Un cerchio completo è2 * Math.PIradianti.counterclockwise— un boolean opzionale. Passatrueper percorrere l'arco in direzione opposta (il valore predefinito èfalse).
Poiché gli angoli sono in radianti, è comodo convertire i gradi con una piccola funzione di supporto:
function toRadians(degrees) {
return degrees * Math.PI / 180;
}
// e.g. a quarter turn:
ctx.arc(125, 75, 50, 0, toRadians(90));Quindi 90 gradi corrisponde a Math.PI / 2, 180 gradi a Math.PI e 360 gradi a 2 * Math.PI.
Un cerchio completo va da 0 a 2 * Math.PI. Come per qualsiasi percorso, è necessario chiamare stroke() o fill() per renderlo visibile:
<!DOCTYPE html>
<html>
<head>
<title>Title of the document</title>
</head>
<body>
<canvas id="canvas" width="250" height="150" role="img"
aria-label="A blue filled circle" style="border:1px solid #dddddd;">
A filled blue circle.
</canvas>
<script>
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
if (ctx) {
ctx.beginPath();
ctx.arc(125, 75, 50, 0, 2 * Math.PI); // center (125,75), radius 50, full circle
ctx.fillStyle = "#1c87c9";
ctx.fill();
}
</script>
</body>
</html>Per disegnare invece un semicerchio, termina l'arco a Math.PI radianti invece che a 2 * Math.PI.
Dove andare dopo
Una volta che hai familiarità con forme e percorsi, esplora il resto del tutorial su Canvas:
- Coordinate del canvas — la griglia in maggior dettaglio.
- Testo su canvas — scrivere testo con
fillText()estrokeText(). - Gradienti su canvas — gradienti di colore lineari e radiali.
- Immagini su canvas — disegnare immagini con
drawImage(). - Riferimento canvas — l'elenco completo di proprietà e metodi.