L'élément<canvas>
est
une zone dans laquelle il va être possible de dessiner au moyen du JavaScript. Cet élément fait son apparition dans
la spécification HTML5, mais existe depuis plusieurs années déjà. Il a été développé par Apple pour son navigateur
Safari. Firefox a été un des premiers navigateurs à l'implémenter, suivi par Opera et Chrome. Les dernières versions
d'Internet Explorer supportent également cet élément.
Canvas est un gros sujet qui mériterait un cours à lui tout seul. Tout au long de ce chapitre d'initiation, nous allons découvrir les bases de ce nouvel élément !
La première chose à faire est d'insérer le canvas :
id="canvas" width="150" height="150"
Désolé, votre navigateur ne supporte pas Canvas. Mettez-vous à jour
Dès que c'est fait, on accède au canvas :
var canvas = document.querySelector('#canvas');
var context = canvas.getContext('2d');
Une fois qu'on a le canvas, il faut
accéder à ce qu'on appelle son contexte, avecgetContext()
.
Il n'y a pour l'instant qu'un seul contexte disponible : la deux dimensions (2D). Il est prévu que les navigateurs
gèrent un jour la 3D, mais ça reste expérimental à l'heure actuelle.
Dessiner avec Canvas se fait par le biais de coordonnées. Le coin supérieur gauche du canvas est de coordonnées (0,0). Si on descend ou qu'on va vers la droite, on augmente les valeurs. Ça ne change finalement pas trop de ce qu'on connaît, par exemple pour le positionnement absolu en CSS.
On va utiliser les méthodes pour tracer des lignes et des formes géométriques.
Traçons un rectangle de 50 sur 80 pixels :
context.fillStyle = "gold";
context.fillRect(0, 0, 50, 80);
Dans un premier temps, on choisit une couleur
avecfillStyle
, comme un peintre qui trempe son pinceau avant de
commencer son tableau. Puis, avecfillRect()
, on trace un rectangle.
Les deux premiers paramètres sont les coordonnées du sommet supérieur gauche du rectangle que nous voulons tracer.
Le troisième paramètre est la largeur du rectangle, et le quatrième est la hauteur. Autrement dit
:fillrect(x, y, largeur, hauteur)
.
Si on veut centrer ce rectangle, il faut s’appliquer à quelques calculs pour spécifier les coordonnées :
context.fillRect(50, 35, 50, 80);
On recommence tout, et on centre le rectangle. Dès que c'est fait, on ajoute un carré de 40 pixels d'une couleur semi-transparente :
context.fillStyle = "gold";
context.fillRect(50, 35, 50, 80);
context.fillStyle = "rgba(23, 145, 167, 0.5)";
context.fillRect(40, 25, 40, 40);
La
propriétéfillStyle
peut recevoir diverses valeurs : le nom de la
couleur, un code hexadécimal (sans oublier le#
devant), une valeur
RGB, HSL ou HSLA ou, comme ici, une valeur RGBA. Dans le cas d'une valeur RGBA, le quatrième paramètre est
l'opacité, définie sur une échelle de 0 à 1, le 0 étant transparent et le 1 opaque. Comme on peut le voir, le carré
a été dessiné par-dessus le rectangle :
Nous avons créé des formes pleines, mais il est également possible de
créer des formes creuses, avec juste un contour. Canvas considère deux types de formes
:fill
etstroke
. Une
formefill
est une forme remplie, comme nous avons fait précédemment, et une
formestroke
est une forme vide pourvue d'un contour. Si pour créer un
rectanglefill
on
utilisefillRect()
, pour créer un
rectanglestroke
on va utiliserstrokeRect()
!
context.strokeStyle = "gold";
context.strokeRect(50, 35, 50, 80);
context.fillStyle = "rgba(23, 145, 167, 0.5)";
context.fillRect(40, 25, 40, 40);
Comme il s'agit d'un contour, il est possible de choisir
l'épaisseur à utiliser. Cela se fait avec la propriétélineWidth
:
context.lineWidth = "5";
context.strokeStyle = "gold";
context.strokeRect(50, 35, 50, 80);
context.fillStyle = "rgba(23, 145, 167, 0.5)";
context.fillRect(40, 25, 40, 40);
Une
dernière méthode existe en ce qui concerne les rectangles :clearRect(x, y,
largeur, hauteur)
. Cette méthode agit comme une gomme, c'est-à-dire qu'elle va effacer du canvas les
pixels délimités par le rectangle. Tout commefillRect()
, on lui
fournit les coordonnées des quatre sommets.clearRect()
est utile pour
faire des découpes au sein des formes, ou tout simplement pour effacer le contenu du canvas.
context.strokeStyle = "gold";
context.strokeRect(50, 35, 50, 80);
context.fillStyle = "rgba(23, 145, 167, 0.5)";
context.fillRect(40, 25, 40, 40);
context.clearRect(45, 40, 30, 10);
Canvas fournit peu de formes géométriques. Il y a le rectangle, les arcs et… c'est tout. Mais pour compléter ce manque, Canvas dispose de chemins ainsi que de courbes de Bézier cubiques et quadratiques.
Les chemins vont nous permettre de créer des lignes et des polygones.
Pour ce faire, plusieurs nouvelles méthodes
:beginPath()
etclosePath()
,moveTo()
,lineTo()
,stroke()
et
son équivalentfill()
.
Comme pour la création de rectangles, la création de chemins se fait
par étapes successives. On commence par initier un nouveau chemin avecbeginPath()
.
Ensuite, avecmoveTo()
, on déplace le « crayon » à l'endroit où on
souhaite commencer le tracé : c'est le point de départ du chemin. Puis, on
utiliselineTo()
pour indiquer un deuxième point, un troisième, etc.
Une fois tous les points du chemin définis, on applique au
choixstroke()
oufill()
:
context.strokeStyle = "rgb(23, 145, 167)";
context.beginPath();
context.moveTo(20, 20); // 1er point
context.lineTo(130, 20); // 2e point
context.lineTo(130, 50); // 3e
context.lineTo(75, 130); // 4e
context.lineTo(20, 50); // 5e
context.closePath(); // On relie le 5e au 1er
context.stroke();
closePath()
n'est pas nécessaire ; il termine le chemin pour nous, en
reliant le dernier point au tout premier. Si on veut une forme fermée, viastroke()
,
c'est assez pratique. Par contre, si on veut remplir la forme
avecfill()
, la forme sera fermée automatiquement,
doncclosePath()
est inutile.
En
plus des lignes droites, il est possible de tracer des arcs de cercle, avec la
méthodearc(x, y, rayon, angleDepart, angleFin, sensInverse)
. Les
angles sont exprimés en radians (oui, rappelez-vous vos cours de trigonométrie !). Avec les
arcs,x
ety
sont les coordonnées du
centre de l'arc. Les
paramètresangleDepart
etangleFin
définissent
les angles de début et de fin de l'arc. Comme dit plus haut, c'est exprimé en radians, et non en degrés.
context.beginPath(); // Le cercle extérieur
context.arc(75, 75, 50, 0, Math.PI * 2); // Ici le calcul est simplifié
context.stroke();
context.beginPath(); // La bouche, un arc de cercle
context.arc(75, 75, 40, 0, Math.PI); // Ici aussi
context.fill();
context.beginPath(); // L'œil gauche
context.arc(55, 70, 20, (Math.PI / 180) * 220, (Math.PI / 180) * 320);
context.stroke();
context.beginPath(); // L'œil droit
context.arc(95, 70, 20, (Math.PI / 180) * 220, (Math.PI / 180) * 320);
context.stroke();
Pour chaque arc, il est plus propre et
plus facile de commencer un nouveau chemin avecbeginPath()
.
moveTo()
Comme on l'a vu plus haut,moveTo()
permet
de déplacer le « crayon » à l'endroit où l'on souhaite commencer un chemin. Mais cette méthode peut aussi être
utilisée pour effectuer des « levées de crayon » au sein d'un même chemin :
context.beginPath(); // La bouche, un arc de cercle
context.arc(75, 75, 40, 0, Math.PI);
context.fill();
context.beginPath(); // Le cercle extérieur
context.arc(75, 75, 50, 0, Math.PI * 2);
context.moveTo(41, 58); // L'œil gauche
context.arc(55, 70, 20, (Math.PI / 180) * 220, (Math.PI / 180) * 320);
context.moveTo(81, 58); // L'œil droit
context.arc(95, 70, 20, (Math.PI / 180) * 220, (Math.PI / 180) * 320);
context.stroke();
Et si on retire les
deuxmoveTo()
, on obtient quelque chose comme ça :
Il est également possible de réaliser des courbes, par le biais de courbes de Bézier. Deux types de courbes sont disponibles : cubique et quadratique. Ce genre de courbes est relativement connu, surtout si vous avez déjà utilisé des logiciels de dessin comme Adobe Photoshop ou The GIMP. Les courbes sont définies par les coordonnées des tangentes qui servent à la construction des courbes. Voici les deux types de courbes, avec les tangentes colorées en gris :
Une courbe quadratique sera dessinée
parquadraticCurveTo()
, alors qu'une courbe cubique le sera
parbezierCurveTo()
:
quadraticCurveTo(cp1X, cp1Y, x, y)
bezierCurveTo(cp1X, cp1Y, cp2X, cp2Y, x, y)
Les courbes sont définies par leurs
points d'arrivée (x
ety
)
et par les points de contrôle. Dans le cas d'une courbe de Bézier cubique, deux points sont nécessaires. La
difficulté des courbes de Bézier est de connaître les valeurs utiles pour les points de contrôle. C'est d'autant
plus complexe qu'on ne voit pas en temps réel ce qu'on fait… Ce genre de courbes est donc puissant, mais complexe à
mettre en œuvre.
Voici une variante du logo JavaScript à partir d'un rectangle arrondi :
context.beginPath();
context.moveTo(131, 119);
context.bezierCurveTo(131, 126, 126, 131, 119, 131);
context.lineTo(30, 131);
context.bezierCurveTo(23, 131, 18, 126, 18, 119);
context.lineTo(18, 30);
context.bezierCurveTo(18, 23, 23, 18, 30, 18);
context.lineTo(119, 18);
context.bezierCurveTo(126, 18, 131, 23, 131, 30);
context.lineTo(131, 119);
context.closePath();
context.fillStyle = "rgb(23, 145, 167)";
context.fill();
context.font = "68px Calibri,Geneva,Arial";
context.fillStyle = "white";
context.fillText("js", 84, 115);
Ce n'est pas compliqué à utiliser,
c'est le même principe qu'arc()
. Ce qu'il y a de difficile ici est de
s'y retrouver dans les coordonnées.
Il
est possible d'insérer des images au sein d'un canvas. Pour ce faire, on utilisera la
méthodedrawImage(image, x, y)
, mais attention : pour qu'une image
puisse être utilisée, elle doit au préalable être accessible via un objetImage
ou
un élément<img />
. Il est également possible d'insérer un canvas dans
un canvas ! En effet, le canvas que l'on va insérer est considéré comme une image.
Insérons l'âne Zozor du Site du Zéro au sein du canvas :
var zozor = new Image();
zozor.src = 'zozor.png'; // Image de 80x80 pixels
context.drawImage(zozor, 35, 35);
On aurait pu récupérer une image déjà
présente dans la page :<img id="myZozor" src="zozor.png" alt="Zozor assis" />
var zozor = document.querySelector('#myZozor');
context.drawImage(zozor, 35, 35);
Attention aux grandes images : si
l'image est trop longue à charger, elle sera affichée de façon saccadée au sein du canvas. Une solution est
d'utiliseronload
pour déclencher le dessin de l'image une fois qu'elle
est chargée :
var zozor = new Image();
zozor.src = 'zozor.png';
zozor.addEventListener('load', function() {
context.drawImage(zozor, 35, 35);
});
drawImage(image, x, y,
largeur, hauteur)
possède deux paramètres supplémentaires facultatifs
:largeur
ethauteur
, qui
permettent de définir la largeur et la hauteur que l'image occupera une fois incrustée dans le canvas. Si la
diminution de la taille des images ne pose pas trop de problèmes, évitez toutefois de les agrandir, au risque de
voir vos images devenir floues.
context.drawImage(zozor, 35, 35, 40, 40);
Ici, l'image est réduite de moitié, puisque de base elle fait 80 pixels sur 80 pixels.
Quatre paramètres supplémentaires et optionnels s'ajoutent
àdrawImage()
. Ils permettent de recadrer l'image, c'est-à-dire de
prélever une zone rectangulaire au sein de l'image afin de la placer dans le canvas :
drawImage(image, sx, sy, sLargeur, sHauteur, dx, dy, dLargeur, dHauteur)
Les paramètres commençant par s indiquent la source, c'est-à-dire l'image, ceux commençant par d indiquent la destination, autrement dit le canvas :
Toute la difficulté est donc de ne pas s’emmêler les pinceaux dans les paramètres :
var zozor = document.querySelector('#plush');
context.drawImage(zozor, 99, 27, 100, 100, 25, 25, 100, 100);
Comment faire se répéter une image pour, par exemple, créer un fond ? C'est possible de faire une double
bouclefor
et d'insérer plusieurs fois la même image. Mais il y a plus
simple : les patterns. On parle aussi de motifs en français. Un pattern est une image qui se répète
comme un papier peint. Pour en créer un, on utilise la méthodecreatePattern(image,
type)
. Le premier argument est l'image à utiliser, et le deuxième est le type de pattern. Différents types
existent, mais seulrepeat
semble reconnu par la plupart des
navigateurs :
var zozor = new Image();
zozor.src = 'zozor.png';
zozor.addEventListener('load', function() {
var pattern = context.createPattern(zozor, 'repeat');
context.fillStyle = pattern;
context.fillRect(0, 0, 150, 150);
});
La façon de procéder est un peu
étrange, puisqu'il faut passer le pattern àfillStyle
, et ensuite
créer un rectangle plein qui recouvre l'entièreté du canvas. En clair, il s'agit de créer un rectangle avec une
image qui se répète comme fond.
Pour
écrire du texte au sein d'un canvas, il y a les
méthodesfillText()
etstrokeText()
,
secondées par la propriétéfont
, qui permet de définir le style du
texte :
context.fillStyle = "rgba(23, 145, 167, 1)";
context.fillRect(50, 50, 50, 50);
context.font = "bold 22pt Calibri,Geneva,Arial";
context.fillStyle = "#fff";
context.fillText("js", 78, 92);
Les
méthodesfillStyle
etstrokeStyle
sont
toujours utilisables, puisque les textes sont considérés comme des formes au même titre que les rectangles ou les
arcs.
La
propriétéfont
reçoit des informations sur la police à utiliser, à
l'exception de la couleur, qui est gérée
parstrokeStyle
etfillStyle
.
Dans l'exemple qui va suivre, nous allons utiliser un texte en Calibri, de 22 points et mis en gras. Ça ressemble à
du CSS en fait.
fillText()
reçoit
trois paramètres : le texte et les
positionsx
ety
de la ligne
d'écriture du texte :
Un quatrième paramètre peut être ajouté : la largeur maximale que le texte doit utiliser.
La propriétélineCap
permet
de définir la façon dont les extrémités des chemins sont affichées. Trois valeurs sont admises
:butt
, celle par
défaut,round
etsquare
.
Une image vaut mieux qu'un long discours, alors voici trois lignes, chacune avec
unlineCap
différent :
lineCap
s'utilise
de la même façon quelineWidth
, exemple :
context.beginPath();
context.lineCap = 'round';
context.moveTo(75, 20);
context.lineTo(75, 130);
context.stroke();
Comment gérer la façon dont les angles des chemins sont affichés ?
Simple, aveclineJoin
. Cette propriété reçoit elle aussi trois valeurs
différentes
:round
,bevel
etmiter
,
ce dernier étant la valeur par défaut. Comme précédemment, une image sera plus explicite :
À l'heure actuelle, que ferions-nous sans dégradés ? Canvas propose deux types de dégradés : linéaire et radial.
Pour créer un dégradé, on commence par créer un objetcanvasGradient
que
l'on va assigner àfillStyle
. Pour créer un tel objet, on utilise au
choixcreateLinearGradient()
oucreateRadialGradient()
.
On a besoin de quatre paramètres pour créer un dégradé linéaire :
createLinearGradient(debutX, debutY, finX, finY)
debutX
etdebutY
sont les
coordonnées du point de départ du dégradé,
etfinX
etfinY
sont les
coordonnées de fin. Faisons un dégradé :
var linear = new context.createLinearGradient(0, 0, 150, 150);
context.fillStyle = linear;
Ce n'est pas suffisant, puisqu'il
manque les informations sur les couleurs. On va ajouter ça avecaddColorStop(position,
couleur)
. Le premier paramètre,position
, est une valeur
comprise entre 0 et 1. C'est la position relative de la couleur par rapport au dégradé. Si on met 0.5, la couleur
commencera au milieu :
var linear = context.createLinearGradient(0, 0, 0, 150);
linear.addColorStop(0, 'white');
linear.addColorStop(1, '#1791a7');
context.fillStyle = linear;
context.fillRect(20, 20, 110, 110);
Pour modifier l'inclinaison du
dégradé, il faut modifier les paramètres decreateLinearGradient()
.
Par exemple, si on metcreateLinearGradient(0, 0, 150, 150)
, la fin du
dégradé sera dans le coin inférieur droit, et donc incliné à 45 degrés.
Il est possible de mettre plus de
deuxaddColorStop()
. Voici un exemple avec quatre :
var linear = context.createLinearGradient(0, 0, 0, 150);
linear.addColorStop(0, 'white');
linear.addColorStop(0.5, '#1791a7');
linear.addColorStop(0.5, 'orange');
linear.addColorStop(1, 'white');
context.fillStyle = linear;
context.fillRect(10, 10, 130, 130);
Du côté des dégradés radiaux, il faut six paramètres :
createRadialGradient(centreX, centreY, centreRayon, finX, finY, finRayon)
Un dégradé radial est défini par deux choses : un premier cercle (le centre) qui fait office de point de départ et un second qui fait office de fin. Ce qui est pratique, c'est que les deux cercles n'ont pas besoin d'avoir la même origine, ce qui permet d'orienter le dégradé :
var radial = context.createRadialGradient(75, 75, 0, 130, 130, 150);
radial.addColorStop(0, '#1791a7');
radial.addColorStop(1, 'white');
context.fillStyle = radial;
context.fillRect(10, 10, 130, 130);
Ici, le cercle du centre est… au centre du canvas, et celui de fin en bas à droite. Grâce aux dégradés radiaux, il est possible de créer des bulles assez facilement. La seule condition est que la couleur de fin du dégradé soit transparente, ce qui nécessite l'utilisation d'une couleur RGBA ou HSLA :
var radial1 = context.createRadialGradient(0, 0, 10, 100, 20, 150); // fond
radial1.addColorStop(0, '#ddf5f9');
radial1.addColorStop(1, '#ffffff');
var radial2 = context.createRadialGradient(75, 75, 10, 82, 70, 30); // bulle orange
radial2.addColorStop(0, '#ffc55c');
radial2.addColorStop(0.9, '#ffa500');
radial2.addColorStop(1, 'rgba(245,160,6,0)');
var radial3 = context.createRadialGradient(105, 105, 20, 112, 120, 50); // bulle turquoise
radial3.addColorStop(0, '#86cad2');
radial3.addColorStop(0.9, '#61aeb6');
radial3.addColorStop(1, 'rgba(159,209,216,0)');
context.fillStyle = radial1;
context.fillRect(10, 10, 130, 130);
context.fillStyle = radial2;
context.fillRect(10, 10, 130, 130);
context.fillStyle = radial3;
context.fillRect(10, 10, 130, 130);
Ce qui donne un dégradé de fond avec deux bulles de couleur :
La méthodesave()
a pour
fonction de sauvegarder l'état graphique du canvas, c'est-à-dire les informations concernant les styles appliqués au
canvas. Ces informations
sontfillStyle
,strokeStyle
,lineWidth
,lineCap
,lineJoin
ainsi
quetranslate()
etrotate()
,
que nous allons découvrir plus bas.
À chaque appel de la
méthodesave()
, l'état graphique courant est sauvegardé dans une pile.
Pour restaurer l'état précédent, il faut utiliserrestore()
.
La translation permet de déplacer le repaire d'axes du canvas. L'idée
est de placer le point (0,0) à l'endroit où l'on souhaite dessiner une forme. De cette manière, on dessine la forme
sans se soucier des calculs de son emplacement, ce qui peut se révéler utile quand on insère des formes complexes.
Une fois que les formes sont dessinées, on replace les axes à leur point d'origine. Et, bonne
nouvelle,save()
etrestore()
prennent
en compte les translations !
Les translations se font avec la
méthodetranslate(x,
y)
.x
est l'importance du déplacement sur l'axe des
abscisses ety
sur l'axe des ordonnées : les valeurs peuvent donc être
négatives.
context.save();
context.translate(40, 40);
context.fillStyle = "teal";
context.fillRect(0, 0, 50, 50);
context.restore();
context.fillStyle = "orange";
context.fillRect(0, 0, 50, 50);
On commence par sauvegarder l'état du
canvas. Ensuite, on déplace l'origine des axes au point (40,40) et on y dessine un carré bleu-gris. Dès que c'est
fait, on restaure l'état, ce qui a pour conséquence de replacer l'origine des axes au point (0,0) du canvas. Là, on
dessine le carré orange. Grâce à la translation, on a pu laisser (0,0) comme coordonnées
defillRect()
!
Les rotations permettent d'appliquer une rotation aux axes du canvas.
Le canvas tourne autour de son point d'origine (0,0). La
méthoderotate()
reçoit un seul paramètre : l'angle de rotation
spécifié en radians. Il est possible de combiner une rotation et une translation, comme le montre l'exemple suivant
:
context.translate(75,75);
context.fillStyle = "teal";
context.rotate((Math.PI / 180) * 45);
context.fillRect(0, 0, 50, 50);
context.fillStyle = "orange";
context.rotate(Math.PI / 2);
context.fillRect(0, 0, 50, 50);
context.fillStyle = "teal";
context.rotate(Math.PI / 2);
context.fillRect(0, 0, 50, 50);
context.fillStyle = "orange";
context.rotate(Math.PI / 2);
context.fillRect(0, 0, 50, 50);
On place l'origine des axes au centre
du canvas avectranslate()
. On opère une première rotation de 45
degrés et on dessine un carré bleu-gris. Ensuite, on fait une deuxième rotation de 90 degrés et on dessine un carré
orange. On continue de tourner les axes de 90 degrés et on dessine un nouveau carré bleu-gris. On fait une dernière
rotation et on dessine un carré orange.
La gestion des animations avec Canvas est quasi inexistante ! En effet, Canvas ne propose rien pour animer les formes, les déplacer, les modifier… Pour arriver à créer une animation avec Canvas, il faut :
Dessiner une image ;
Effacer tout ;
Redessiner une image, légèrement modifiée ;
Effacer tout ;
Redessiner une image, légèrement modifiée ;
Et ainsi de suite…
En clair, il suffit d'appeler une fonction qui, toutes les x secondes, va redessiner le canvas. Il est également possible d'exécuter des fonctions à la demande de l'utilisateur, mais ça, c'est assez simple.
« Framerate » est un mot anglais pour évoquer le nombre d'images
affichées par seconde. Les standards actuels définissent que chaque animation est censée, en théorie, afficher un
framerate de 60 images par seconde pour paraître fluide pour l’œil humain. Parfois, ces 60 images peuvent ne pas
être toutes affichées en une seconde à cause d'un manque de performances, on appelle cela une baisse de framerate et
cela est généralement perçu par l'œil humain comme étant un ralenti saccadé. Ce problème est peu appréciable et est
malheureusement trop fréquent avec les
fonctionssetTimeout()
etsetInterval()
,
qui n'ont pas été conçues à l'origine pour ce genre d'utilisations…
Une solution à ce problème a été développée
:requestAnimationFrame()
. À chacune de ses exécutions, cette fonction
va déterminer à quel moment elle doit se redéclencher de manière à garder un framerate de 60 images par seconde. En
clair, elle s'exécute de manière à afficher quelque chose de fluide.
Reprenons le canvas que nous venons de réaliser :
En nous basant sur son code, nous allons faire tourner le
dessin dans le sens des aiguilles d'une montre. Pour commencer, il faut créer une fonction qui sera appelée
parwindow.requestAnimationFrame()
. Il s'agira de la
fonctiondraw(angle)
. Cette fonction efface le canvas et le redessine
avec un angle de rotation incrémenté de quelques degrés.
window.addEventListener('load', function() {
var canvas = document.querySelector('#canvas');
var context = canvas.getContext('2d');
function draw(angle) {
context.save();
context.clearRect(0, 0, 150, 150);
context.translate(75,75);
context.fillStyle = "teal";
context.rotate((Math.PI / 180) * (45 + angle));
context.fillRect(0, 0, 50, 50);
context.fillStyle = "orange";
context.rotate(Math.PI / 2);
context.fillRect(0, 0, 50, 50);
context.fillStyle = "teal";
context.rotate(Math.PI / 2);
context.fillRect(0, 0, 50, 50);
context.fillStyle = "orange";
context.rotate(Math.PI / 2);
context.fillRect(0, 0, 50, 50);
context.restore();
angle = angle + 2;
if (angle >= 360) angle = 0;
window.requestAnimFrame(function() { draw(angle) });
}
draw(0);
});
La
variableangle
représente le décalage. Lors du premier appel
dedraw()
, le décalage vaut 0. Après le premier appel, on
incrémenteangle
de 2 degrés, et donc, lors du prochain appel, tout le
canvas sera dessiné avec un décalage de 2 degrés. On réincrémente de 2, et on redessine. Ainsi de suite, pour donner
l'illusion que toute la forme bouge, alors qu'on ne fait que spécifier un angle de rotation de départ qui va
croissant.
Les possibilités d'animation de Canvas
sont toutes basées sur le même principe
:window.requestAnimationFrame()
. Ici, il s'agissait de créer un effet
de rotation, mais il est possible de créer une courbe qui s'étire (une courbe de Bézier pour laquelle on incrémente
les valeurs), d'animer une balle qui rebondit… Bref, les possibilités sont nombreuses, mais une fois que le principe
est acquis, il est facile de se débrouiller.
Ce chapitre
d'introduction à Canvas est désormais terminé. Toutes les ficelles de ce nouvel élément n'ont pas été vues, mais le
principal est là. Il ne tient qu'à vous de vous exercer et d'approfondir votre connaissance
de<canvas>
!
L'élément<canvas>
est une zone de la page dans laquelle il est
possible de dessiner des formes via le JavaScript. Canvas supporte également un système basique pour créer des
animations.
Le dessin se
fait par l'intermédiaire de coordonnées dont l'origine des axes (le
point(0,0)
) est le coin supérieur gauche du canvas.
Une fois dessinée, une forme n'est plus manipulable. Il est nécessaire d'effacer le contenu du canvas, puis de redessiner.
Canvas ne supporte que quelques formes : le rectangle, l'arc de cercle, et les courbes de Bézier quadratiques et cubiques.
Il est également possible d'insérer des images au sein du canvas, tout comme de créer des dégradés ou d'ajouter du texte.
L'utilisation des rotations et des translations facilite les calculs des coordonnées et donc la création du dessin.