Introduction
Depuis Firefox 1.5, Firefox comprend un nouvel élément HTML servant à dessiner programmatiquement. L'élément <canvas>
est basé sur la spécification canvas du WHATWG, elle-même basée sur la balise <canvas>
d'Apple implémentée dans Safari. Celui-ci peut être utilisé pour afficher des graphes, des élements d'interface, et d'autres éléments graphiques personnalisés sur le client.
<canvas>
crée une surface de dessin de taille fixe, ou canevas, exposant un ou plusieurs contextes de rendu. Nous nous concentrerons sur le contexte de rendu 2D (c'est d'ailleurs le seul contexte de rendu actuellement défini). Dans le futur, d'autres contextes peuvent fournir différents types de rendu. Par exemple, il est probable qu'un contexte 3D basé sur OpenGL ES sera ajouté à la spécification <canvas>
.
Le contexte de rendu 2D
Un exemple simple
Pour commencer, voici un exemple simple qui dessine deux rectangles ayant une intersection, l'un d'entre-eux possédant une transparence alpha :
<html> <head> <script type="application/x-javascript"> function draw() { var canvas = document.getElementById("canvas"); var ctx = canvas.getContext("2d"); ctx.fillStyle = "rgb(200,0,0)"; ctx.fillRect (10, 10, 55, 50); ctx.fillStyle = "rgba(0, 0, 200, 0.5)"; ctx.fillRect (30, 30, 55, 50); } </script> </head> <body onload="draw()"> <canvas id="canvas" width="300" height="300"></canvas> </body> </html>
La fonction draw
récupère l'élément canvas
, et ensuite son contexte 2d
. L'objet ctx
peut ensuite être utilisé pour dessiner réellement vers le canevas. L'exemple remplit simplement les deux rectangles, en positionnant fillStyle
à deux couleurs différentes à l'aide des spécifications de couleur CSS et d'un appel à fillRect
. Le second appel à fillStyle
utilise rgba()
pour spécifier une valeur alpha parmi les informations de couleur.
Les appels à fillRect
, strokeRect
et clearRect
affichent un rectangle plein, surligné ou vide. Pour afficher des formes plus complexes, on utilise des chemins.
Utilisation de chemins
La fonction beginPath
commence un nouveau chemin, et moveTo
, lineTo
, arcTo
, arc
et des méthodes similaires sont utilisées pour ajouter des segments au chemin. Le chemin peut être fermé à l'aide de closePath
. Une fois que le chemin est créé, vous pouvez utiliser fill
ou stroke
pour afficher celui-ci sur le canevas.
<html> <head> <script type="application/x-javascript"> function draw() { var canvas = document.getElementById("canvas"); var ctx = canvas.getContext("2d"); ctx.fillStyle = "red"; ctx.beginPath(); ctx.moveTo(30, 30); ctx.lineTo(150, 150); ctx.bezierCurveTo(60, 70, 60, 70, 70, 150); ctx.lineTo(30, 30); ctx.fill(); } </script> </head> <body onload="draw()"> <canvas id="canvas" width="300" height="300"></canvas> </body> </html>
L'appel à fill()
ou stroke()
provoque l'utilisation du chemin. Pour être rempli ou dessiné à nouveau, le chemin devra être recréé.
État graphique
Les attributs du contexte comme fillStyle
, strokeStyle
, lineWidth
et lineJoin
font partie de l'état graphique courant. Le contexte fournit deux méthodes, save()
et restore()
, qui peuvent être utilisées pour déplacer l'état courant vers et depuis la pile d'états.
Un exemple plus compliqué
Voici un exemple un petit peu plus compliqué, qui utilise des chemins, des états et introduit également la matrice de transformation courante. Les méthodes du contexte translate()
, scale()
et rotate()
transforment toutes la matrice courante. Tous les points affichés sont au préalable transformés par cette matrice.
<html> <head> <script type="application/x-javascript"> function dessineNoeudPap(ctx, fillStyle) { ctx.fillStyle = "rgba(200,200,200,0.3)"; ctx.fillRect(-30, -30, 60, 60); ctx.fillStyle = fillStyle; ctx.globalAlpha = 1.0; ctx.beginPath(); ctx.moveTo(25, 25); ctx.lineTo(-25, -25); ctx.lineTo(25, -25); ctx.lineTo(-25, 25); ctx.closePath(); ctx.fill(); } function point(ctx) { ctx.save(); ctx.fillStyle = "black"; ctx.fillRect(-2, -2, 4, 4); ctx.restore(); } function dessine() { var canvas = document.getElementById("canvas"); var ctx = canvas.getContext("2d"); // notez que toutes les autres translations sont relatives à // celle-ci ctx.translate(45, 45); ctx.save(); //ctx.translate(0, 0); // non nécessaire dessineNoeudPap(ctx, "red"); point(ctx); ctx.restore(); ctx.save(); ctx.translate(85, 0); ctx.rotate(45 * Math.PI / 180); dessineNoeudPap(ctx, "green"); point(ctx); ctx.restore(); ctx.save(); ctx.translate(0, 85); ctx.rotate(135 * Math.PI / 180); dessineNoeudPap(ctx, "blue"); point(ctx); ctx.restore(); ctx.save(); ctx.translate(85, 85); ctx.rotate(90 * Math.PI / 180); dessineNoeudPap(ctx, "yellow"); point(ctx); ctx.restore(); } </script> </head> <body onload="dessine()"> <canvas id="canvas" width="300" height="300"></canvas> </body> </html>
Ceci définit deux méthodes dessineNoeudPap
et point
, qui sont appelées 4 fois. Avant chaque appel, translate()
et rotate()
sont utilisées pour définir la matrice de transformation courante, qui à son tour positionne le point et le nœud papillon. point
affiche un petit carré noir centré sur (0, 0)
. Ce point est déplacé par la matrice de transformation. dessineNoeudPap
affiche un chemin simple en forme de nœud papillon en utilisant le style de remplissage fourni en paramètre.
Comme les opérations de matrices sont cumulatives, save()
et restore()
sont utilisées autour de chaque jeu d'appels afin de restaurer l'état initial du canevas. Une chose à surveiller est que la rotation se passe toujours autour de l'origine courante ; donc une séquence translate() rotate() translate()
donnera des résultats différents d'une série d'appels translate() translate() rotate()
.
Compatibilité avec le <canvas> d'Apple
Pour la plus grande partie, le <canvas>
de Mozilla est compatible avec celui d'Apple et d'autres implémentations. Il convient cependant d'être averti de quelques problèmes, décrits ci-dessous.
Balise </canvas>
requise
Dans l'implémentation d'Apple Safari, <canvas>
est un élément fortement semblable à l'élément <img>
; il ne doit pas forcément avoir de balise de fermeture. Cependant, pour que <canvas>
puisse être utilisé à grande échelle sur le Web, il est important de pouvoir fournir facilement du contenu alternatif. C'est pourquoi l'implémentation de Mozilla a une balise de fin requise.
Si aucun contenu alternatif n'est nécessaire, un simple <canvas id="foo" ...></canvas>
sera entièrement compatible avec Safari et Mozilla -- Safari ignorera simplement la balise de fermeture.
Si un contenu alternatif est désiré, certaines astuces CSS doivent être utilisées pour masquer le contenu alternatif à Safari (qui doit seulement afficher le canevas), et masquer ces mêmes astuces à Internet Explorer (qui doit afficher le contenu alternatif). À faire : les commandes CSS exactes doivent être fournies par hixie.
Fonctionnalités supplémentaires
Affichage de contenu Web dans un canevas
L'élément canvas
de Mozilla a été étendu avec la méthode drawWindow
. Celle-ci dessine une capture du contenu d'un élément DOM window
dans le canevas. Par exemple,
ctx.drawWindow(window, 0, 0, 100, 200, "rgb(0,0,0)");
affichera le contenu de la fenêtre courante dans le rectangle (0,0,100,200) défini en pixels relatifs au coin en haut à gauche de la fenêtre d'affichage, sur un fond noir, dans le canevas. En spécifiant "rgba(0,0,0,0)" comme couleur, le contenu sera dessiné avec un fond transparent (ce qui sera plus lent).
Avec cette méthode, il est possible de remplir un IFRAME caché avec du contenu arbitraire (par exemple, du texte HTML stylé avec CSS, ou du SVG) et de le dessiner dans un canevas. Celui-ci sera redimensionné, tourné, etc. suivant la transformation courante.
L'extension tab preview de Ted Mielczarek utilise cette technique dans le chrome pour fournir des miniatures de pages Web, et sa source est disponible pour référence.