back to top

L’elemento canvas e le canvas API (parte 1) – Fondamenti

HTML5 introduce l’elemento canvas (tela, area di disegno) e le relative APIs per permettere di generare o modificare elementi grafici (bitmap) con relativa semplicità.

Definizione formale

L’elemento canvas fornisce un’area di disegno che può essere sfruttata dagli scripts (tipicamente codice Javascript) per disegnare on the fly grafici, grafica per videogame, immagini; può avere un contesto (context) primario che è il primo contesto ad essere ottenuto per l’elemento; alla creazione canvas non deve avere un contesto primario.

Il contesto attualmente disponibile è l’HTML Canvas 2D Context (è teoricamente previsto anche un contesto 3D), le cui APIs sono definite in un documento apposito consultabile a questo indirizzo; l’ultimo draft disponibile è datato 6 Gennaio 2012.

N.B.: È errato utilizzare canvas per renderizzare l’intestazione di una pagina, qualora questa dovesse essere particolarmente elaborata graficamente sarebbe opportuno utilizzare un elemento h1 debitamente stilizzato attraverso i CSS.

È consigliabile inserire all’interno dell’elemento del contenuto testuale che agisca come descrizione e fallback qualora non fosse possibile mostrare il bitmap.

Canvas prevede due attributi, utilizzati per controllare la dimensione dell’area disponibile (coordinate space):

  • width: larghezza dell’area di disegno, quando non esplicitata il default è 300px.
  • height: altezza dell’area di disegno, quando non esplicitata il default è 150px.

Alla creazione del canvas e ad ogni resize successivo (ottenuto tramite modifiche su width e height) il bitmap ed ogni context associato vengono (ri)puliti e (re)inizializzati con le nuove dimensioni indicate.

La sintassi base dell’elemento è la seguente:

<canvas id="c_area">Il browser non supporta il tag canvas</canvas>

Il tag così definito rappresenta un’area invisibile di dimensione standard 300×150 pixels; come potete notare è definito un contenuto testuale per il fallback.

La prima operazione da metter in atto per poter iniziare a disegnare è ottenere un context (2D):

// # Come da esempio precedente, nella pagina esiste un elemento 
// # canvas con id="c_area"
var canvasObj = document.getElementById("c_area");

// # Ottengo il contesto (2D)
context = canvasObj.getContext("2d");

Tramite il context possiamo ora iniziare a disegnare; partiamo da un bitmap semplice, una forma geometrica:

// # Colore riempimento, un grigio molto tenue
context.fillStyle = "#ededed";

// # Creazione del rettangolo
context.fillRect(100, 50, 100, 50);

Il codice genera un rettangolo di dimensioni width=100, height=50 e coordinate (100, 50), perfettamente centrato e di colore grigio chiaro.

Ecco il codice completo dell’esempio base:

<!doctype html>
<html>
<head>
<title>La prima forma geometrica</title>
<style>
  canvas {
    border: 1px solid #222;
  }
</style>
<script src="jquery.js"></script>
<script>

// # Al DOM Ready
$(function() {

  // # Ottengo l'oggetto relativo al canvas
  var canvasObj = document.getElementById("c_area");
  context = canvasObj.getContext("2d"); // ottengo il contesto
	
  //# Colore riempimento, un grigio molto tenue
  context.fillStyle = "#ededed";

  // # Creazione del rettangolo
  context.fillRect(100, 50, 100, 50);
});
</script>
</head>
<body>
  <canvas id="c_area">Impossibile mostrare il canvas</canvas>
</body>
</html>

ed il risultato così come mostrato da Firefox:

rectangle

Prima di presentarvi un esempio più elaborato vi fornisco una lista delle principali funzioni esposte dalle APIs riguardanti le forme geometriche:

context.beginPath();

Crea/resetta il path corrente.

context.closePath();

Contrassegna come chiuso il subpath corrente e ne inizia un altro con coordinate di partenza uguali a quelle finali del path appena chiuso.

context.fill();

Colora il subpath con lo stile definito in fillStyle.

context.stroke();

Tratteggia il subpath con lo stile definito in strokeFill.

contextarc(x, y, radius, startAngle, endAngle [, anticlockwise ])

Disegna un arco partendo dalle coordinate (x, y), di raggio radius, angolo di partenza starAngle e angolo di arrivo endAngle; anticlockwise indica la direzione di disegno (false di default, quindi clockwise: senso orario).

context.rect(x, y, w, h)

Disegna un rettangolo (subpath chiuso) a partire dalle coordinate (x, y), di larghezza w, altezza h

context.lineTo(x, y);

Aggiunge il punto di coordinate x, y al subpath corrente, connesso al precedente da una linea retta.

Un primo esempio di utilizzo di canvas

Ora possiamo approcciare l’esempio, generosamente commentato (utilizza jQuery solo per intercettare l’evento DOM ready):

<!doctype html>
<html>
<head>
<title>Un simpatico amico</title>
<script src="jquery.js"></script>
<script>

// # Al DOM Ready
$(function() {

  // # Ottengo l'oggetto relativo al canvas
  var canvasObj = document.getElementById("c_area");
  context = canvasObj.getContext("2d"); // ottengo il contesto
	
  // # "Costanti" per i colori riutilizzati
  var REDHEX   = "#990000";// porpora 
  var BLACKHEX = "#222"; // antracite
  var BLUEHEX  = "#0066cc"; // blu

  // # Definizione inizio path
  context.beginPath();
  
  // # Il viso, un arco a (125, 75) raggio 70, angolo da 0 a 2Math.PI (sfera), clockwise
  context.fillStyle = "#ffcc99";
  context.arc(125, 150, 70, 0, Math.PI*2, true);
  context.fill();
  context.stroke(); // disegno effettivamente la curva
  
  // chiudo il path
  context.closePath();

  // # Sopracciglio sx (arco)
  context.beginPath();
  context.arc(100, 125, 20, 0, Math.PI, true);
  context.stroke();
  context.closePath();

  // # Sopracciglio dx (arco)
  context.beginPath();
  context.arc(150, 125, 20, 0, Math.PI, true);
  context.stroke();
  context.closePath();

  // # occhio sx (sfera)
  context.beginPath();
  context.strokeStyle = BLACKHEX;
  context.fillStyle = BLUEHEX;
  context.arc(100, 135, 5, 0, Math.PI*2, true);
  context.fill();
  context.stroke();
  context.closePath();

  // # occhio dx (sfera)
  context.beginPath();
  context.strokeStyle = BLACKHEX;
  context.fillStyle = BLUEHEX;
  context.arc(150, 135, 5, 0, Math.PI*2, true);
  context.fill();
  context.stroke();
  context.closePath();

  // # naso (sfera)
  context.beginPath();
  context.strokeStyle = BLACKHEX;
  context.fillStyle = REDHEX;
  context.arc(125, 155, 8, 0, Math.PI*2, true);
  context.fill();
  context.stroke();
  context.closePath();

  // # bocca (semisfera)
  context.beginPath();
  context.strokeStyle = REDHEX;
  context.fillStyle = REDHEX;
  context.arc(125, 180, 12, 0, Math.PI, false);
  context.fill();
  context.stroke();
  context.closePath();
	
  // # cappello (rettangolo + linea della tesa)
  context.beginPath();
  context.strokeStyle = BLACKHEX;
  context.fillStyle = BLACKHEX;
  context.moveTo(55, 95);
  context.lineTo(195, 95);
  context.rect(80, 0, 90, 95);
  context.fill();
  context.stroke();
  context.closePath();
});
</script>
</head>
<body>
<article>
<!-- Impostiamo l'altezza a 300px, la width è 300px per default, l'area è un quadrato -->
<canvas id="c_area" height="300px">Impossibile mostrare il canvas</canvas>
</article>
</body>
</html>

Importante: gli angoli devono essere definiti in radianti, ricordo la regola di conversione per cui: radianti = 180/PI gradi; per gli angoli più comuni vale quindi:

  • 30° = Math.PI/6.
  • 60° = Math.PI/3
  • 90° = Math.PI/2
  • 180° = Math.PI
  • 360° = 2*Math.PI

Rammentate le basi di geometria, ecco finalmente il nostro bitmap così come renderizzato in Firefox.

amico bitmap
Pubblicitร 

In questa guida...