• 12 heures
  • Moyenne

Ce cours est visible gratuitement en ligne.

course.header.alt.is_video

course.header.alt.is_certifying

J'ai tout compris !

Mis à jour le 20/11/2019

Introduisez de l’interactivité sur la balise canvas

Connectez-vous ou inscrivez-vous gratuitement pour bénéficier de toutes les fonctionnalités de ce cours !

Interactivité clavier avec la mise en œuvre du onKeyDown

Dans cette partie, nous allons voir comment réaliser une animation interactive simple avec HTML5.

Nous allons pour cela reprendre le concept d'événement JavaScript, et l'adapter au contexte du canvas en prenant deux exemples : le cas d'une interaction clavier et le cas d'un clic souris.

Interaction clavier
Interaction clavier

Comment associer animation et interaction ?

Une des utilisations les plus courantes du clavier consiste à utiliser les touches de flèches pour diriger un objet en mouvement. 

L'exemple qui suit reprend une animation vue au chapitre précédent consistant à déplacer un rectangle sur un axe vertical, du haut vers le bas, et à l'adapter pour prendre en compte une interaction clavier.

Déplacement vertical d'un rectangle au clavier
Déplacement vertical d'un rectangle au clavier

Remémorons-nous le code de l'animation.

<script>
// canvas
var monCanvas = document.getElementById('dessin');
if (monCanvas.getContext){
var ctx = monCanvas.getContext('2d');
// dessin
ctx.fillStyle = "blue";
// translation au centre
ctx.translate(monCanvas.width/2,monCanvas.height/2)
// dessin
ctx.fillRect(0, 0, 200, 20);
} else {
alert('canvas non supporté par ce navigateur');
}
/* fonction de dessin */
function Translation() {
ctx.clearRect(0, 0, monCanvas.width,monCanvas.height);
ctx.translate(2,2);
/* dessin */
ctx.fillRect(0, 0, 200, 20);
i++;
if(i>100) clearInterval(inter);
}
/* incrément */
var i = 0;
/* timer */
var inter = setInterval(Translation, 100);
</script>

On identifie aisément la partie de code définissant le canvas :

// canvas
var monCanvas = document.getElementById('dessin');
if (monCanvas.getContext){
var ctx = monCanvas.getContext('2d');
// dessin
ctx.fillStyle = "blue";
// translation au centre
ctx.translate(monCanvas.width/2,monCanvas.height/2)
// dessin
ctx.fillRect(0, 0, 200, 20);
} else {
alert('canvas non supporté par ce navigateur');
}

De même, on identifie la partie de code permettant de lancer une fonction de dessin à intervalles réguliers :

/* incrément */
var i = 0;
/* timer */
var inter = setInterval(Translation, 100);

Enfin, on identifie la partie de code correspondant à cette fonction de dessin. Au sein de cette dernière, la méthode translate qui, à chaque itération, déplace le contexte d'une quantité 0 suivant x et 2 suivant y. Soit, pour l'instant donc, une translation sur un axe vertical et de haut en bas.

/* fonction de dessin */
function Translation() {
ctx.clearRect(0, 0, monCanvas.width,monCanvas.height);
ctx.translate(2,2);
/* dessin */
ctx.fillRect(0, 0, 200, 20);
i++;
if(i>100) clearInterval(inter);
}

C'est précisément sur ce déplacement suivant X que l'on va jouer.

On remplace ce zéro par une variable que l'on appelle X, que l'on initialise à zéro tout au début du code.

function Translation() {
ctx.clearRect(0, 0, monCanvas.width,monCanvas.height);
ctx.translate(X,2);
/* dessin */
ctx.fillRect(0, 0, 200, 20);
i++;
if(i>100) clearInterval(inter);
}

Ensuite, on installe deux gestionnaires : un pour l'événement keydown, un autre pour l'événement keyup :

document.addEventListener("keydown", down, false);
document.addEventListener("keyup", up, false);

L’événement keydown permet d'affecter à X une valeur 4 ou -4 selon que l'on appuie sur la touche droite ou gauche, l'événement keyup permet de réinitialiser X pour que la chute se fasse verticalement.

function down(e){
// traitement de différents cas
switch(e.keyCode) {
case 39:
// flèche droite
X = 4;
break;
case 37:
// flèche gauche
X = -4;
break;
default:
}
}
function up(e){
X = 0;
}

Cela donne, au final, le code suivant :

<script>
// gestionnaire
var X = 0;
document.addEventListener("keydown", down, false);
document.addEventListener("keyup", up, false);
function down(e){
// traitement de différents cas
switch(e.keyCode) {
case 39:
// flèche droite
X = 4;
break;
case 37:
// flèche gauche
X = -4;
break;
default:
}
}
function up(e){
X = 0;
}
// canvas
var monCanvas = document.getElementById('dessin');
if (monCanvas.getContext){
var ctx = monCanvas.getContext('2d');
// dessin
ctx.fillStyle = "blue";
// translation au centre
ctx.translate(monCanvas.width/2,monCanvas.height/2)
// dessin
ctx.fillRect(0, 0, 20, 20);
} else {
alert('canvas non supporté par ce navigateur');
}
// incrément
var i = 0;
// timer
var inter = setInterval(Translation, 100);
// fonction de dessin
function Translation() {
ctx.clearRect(0, 0, monCanvas.width,monCanvas.height);
ctx.translate(X,2);
// dessin
ctx.fillRect(0, 0, 20, 20);
i++;
if(i>100) clearInterval(inter);
}
</script>

Je vous propose de tester ce code.

Interactivité et animation : principe et mise en œuvre

Dans l'exemple précédent, une interactivité clavier se traduisait par un changement de paramètre dans les méthodes de dessin associées au canvas.

Voyons sur un autre exemple : comment introduire une interactivité souris sur le canvas lui-même. Le canvas étant un objet de la page HTML, on peut, de la même façon que précédemment, lui associer un gestionnaire.

Envisageons le cas suivant : le lieu du canvas où le clic se produit a une importance. Supposons, si l'on reprend l'exercice des cercles qui se déplacent de haut en bas, que l'on souhaite faire disparaître le cercle sur lequel on clique.

Rappelons que le canvas est une image constituée de pixels. L'objet cercle n'existe pas en tant que tel. En d'autres termes, on ne peut pas mettre en œuvre un gestionnaire sur un cercle, mais seulement sur le canvas tout entier.

La solution est la suivante. On se rappelle que le contenu du canvas est redessiné à intervalles réguliers. On installe ainsi un gestionnaire sur le canvas.

Gestionnaire d'événement associé au canvas
Gestionnaire d'événement associé au canvas
  •  Si un clic bas se produit sur le canvas, on détermine la position de ce clic/canvas ;

Identification clic/canvas
Identification clic/canvas

  • on teste si on clique à l'endroit où un cercle est dessiné. Pour que ceci soit possible, il faut à chaque instant disposer d'un tableau des coordonnées du cercle ;

  • si c'est le cas, alors, lors de l'itération suivante, on va redessiner le canvas sans le cercle en question ;

  • la difficulté est maintenant de déterminer la position du clic/canvas.

    Voyons comment mettre tout ça en œuvre.

1. Installer un gestionnaire de clic sur le canvas. Nous l'avons déjà fait plusieurs fois. Ici c'est la syntaxe classique. Si vous préférez utiliser jQuery, vous trouverez facilement la syntaxe événementielle associée, sur le web.

// interactivité sur le canvas
monCanvas.addEventListener("click", clicCanvas, false);

2. Initialiser un tableau avec les coordonnées des cercles. Pour chaque cercle, on définit ainsi les positions selon x et selon selon y de son centre et son rayon ; la signification de la quatrième valeur sera donnée tout à l'heure.

// cercles
cercles = [[100,0,10,1],[150,0,20,1],[180,0,15,1]];

3. Changer les arguments de dessineBalle. Deux arguments : l'indice du cercle dans le tableau (0 pour le premier cercle, 1 pour le deuxième, etc.) et la vitesse de la balle.

// translation du contexte et dessin d'une balle
dessineBalle(0,2);
// translation du contexte et dessin d'une balle
dessineBalle(1,1);
// translation du contexte et dessin d'une balle
dessineBalle(2,3);

4. Modifier dessineBalle pour prendre en compte ce changement ; en profiter pour rajouter une ligne qui modifie à chaque itération la coordonnée suivant y du cercle que l'on dessine. 

// dessin
var R = cercles[idCercle][2];
cercles[idCercle][1]= v*i;
ctx.translate(cercles[idCercle][0],v*i);
ctx.beginPath();
ctx.arc(0, 0, R, 0, 2 * Math.PI, false);

À ce stade, si l'on teste, on a un fonctionnement identique à l'animation précédente. Il nous reste à exploiter le clic et donc à définir la fonction  clicCanvas  donnée plus haut comme argument du gestionnaire de clic sur le canvas.

5. Calculer la position de la souris dans le document. Les coordonnées de la souris par rapport à la page HTML sont les attributs  pageX  et  pageY  de l'événement qui vient de se produire. Facile.

// clic sur le canvas
function clicCanvas(e){
// position de la souris / document
var xSourisDocument = e.pageX;
var ySourisDocument = e.pageY;
}

6. Trouver les coordonnées du canvas dans la page est ici simple : les attributs  offsetLeft  et  offsetTop  d'un élément sont ses positions selon x et y par rapport à son conteneur. Ici, le conteneur du canvas est la page.

Une fois ces coordonnées déterminées, il est facile de déterminer la position du clic/canvas.

// position du canvas / document
var xCanvas = monCanvas.offsetLeft;
var yCanvas = monCanvas.offsetTop;
// position du clic / canvas
xSourisCanvas = xSourisDocument - xCanvas;
ySourisCanvas = ySourisDocument - yCanvas;

7. En bouclant sur le tableau des cercles, on teste si l'un des cercles est concerné. Si c'est le cas, on met le dernier élément du tableau à 0. 

// test si un cercle est cliqué
for (var c=0; c<cercles.length; c++){
var R = cercles[c][2];
if(Math.abs(cercles[c][0]-xSourisCanvas) < R && Math.abs(cercles[c][1]-ySourisCanvas) < R){
cercles[c][3]=0;
/* le break qui suit appelle une réflexion que je vous soumettrai à la fin de la semaine 7 */
break;
}
}

À quoi nous sert ce quatrième élément du tableau des cercles ?

C'est l'étape n° 8 :

8. Il suffit au moment de dessiner un cercle de vérifier que cet élément est à 1 !

// dessin d'une balle : x départ, vitesse / y, rayon
function dessineBalle(idCercle,v){
if(cercles[idCercle][3]==1)}

Je vous propose de tester cela.

Nous venons de voir comment introduire de l’interactivité sur le canvas.

Nous vous proposons à présent un petit exercice pour mettre en oeuvre ce que vous avez appris dans ce chapitre.

Exercice

L'exercice que nous proposons consiste à reprendre le code écrit dans le chapitre précédent pour déplacer un ensemble de balles avec des caractéristiques aléatoires (taille, vitesse, position) et d'y rajouter la possibilité de déplacer un mobile en translation de gauche à droite tout en bas du canvas (cf figure suivante).

Jeu proposé : éviter les balles
Jeu proposé : éviter les balles

Le joueur devra faire en sorte d'éviter ces balles ; sinon, le jeu s'arrête. Un test de collision devra être effectué à chaque itération.

Bon travail !

En résumé

Dans ce chapitre, nous avons découvert comment réaliser une animation interactive simple avec HTML5, en introduisant d’une part une interaction clavier et, dans un autre exercice, un clic souris.

Il nous reste une dernière fonctionnalité à introduire dans ce module : le glisser-déposer. C'est le thème de la prochaine leçon.

À tout de suite.

Exemple de certificat de réussite
Exemple de certificat de réussite