L'interactivité avec la balise HTML5 Canvas

Johnny Simpson

Traducteur

Didier Mouronval

L'élément HTML5 <canvas> donne aux développeurs des possibilités d'interactivité et de dessin jusqu'alors inaccessibles sans l'utilisation de programmes tiers tels que Flash. Dans cet article, nous allons considérer le problème de l'interactivité et comment l'utiliser avec les balises HTML5 <canvas>. Vous pourrez utiliser ces informations pour créer un jeu HTML5 simple.

Cet article est la traduction de A Look at HTML5 Canvas Interactivity, publié sur le blog InsertHTML.

Commentez ♪

- Titre : L'interactivité avec la balise HTML5 Canvas

- Auteur : Johnny Simpson

- Traducteur : Didier Mouronval

- Parution : 22 mai 2012

- Mise à jour : 3 mars 2013

- Licence : Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright ® 2012 Johnny Simpson. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.

Sommaire

- Jouer

- Les entrées clavier

- Le JavaScript

- Les entrées de souris

- Remerciements

Jouer

Jusqu'il y a peu, il était difficile d'imaginer (et de créer) des jeux codés uniquement en HTML et JavaScript. Avec la balise <canvas>, la notion de jeu ou simplement de zone interactive devient envisageable, sans avoir besoin de Flash, qui était traditionnellement considéré comme la seule solution pratique. Pour commencer, attardons-nous sur la gestion du clavier dans un canvas.

Les entrées clavier

La balise <canvas> se comporte comme toute autre balise. Elle possède des attributs width, height et id. Le contenu de la balise correspond à un contenu alternatif pour les navigateurs ne la supportant pas. J'ai aussi défini une fonction à exécuter au chargement de la page et une balise <div> qui contiendra certaines informations, à savoir la quantité de mouvements effectués par l'élément. Nous allons créer un carré que l'on pourra déplacer avec les touches fléchées du clavier. Bien sûr, vous pourrez vous inspirer de cet exemple pour créer beaucoup d'autres fonctionnalités.

<body onload="init();">

<div>
Vous avez bougé de <span id="x" onload="counting(true);">0</span> horizontalement et de <span id="y" onload="counting();">0</span> verticalement !
<br />
Ne laissez pas la boite gagner ! (Utiliser les touches fléchées)
</div>

<canvas id="game" width="640" height="500">
Oh non ! Votre navigateur ne reconnait pas la balise <canvas>.

</canvas>

</body>

Le JavaScript

Le code JavaScript est un petit peu plus compliqué. En JavaScript, on peut savoir quelle touche a été pressée en utilisant e.keyCode. Chaque caractère du clavier possède un identifiant prédéfini que vous pouvez retrouver. Nous souhaitons créer un carré qui se déplace, nous aurons donc besoin des touches fléchées. Pour commencer, copiez le code suivant dans votre fichier JavaScript. Il s'agit juste des variables dont nous aurons besoin.

var canvas, draw, width, height; // Pour dessiner dans le canvas
var downcheck, upcheck, rightcheck, leftcheck; // Pour déterminer la direction

// Position courante
var up = 0;
var down = 0;
var left = 0;
var right = 0;

Ensuite, nous devrons créer une fonction init(), qui détermine ce qu'il faut faire au chargement de la page.

// La fonction principale pour initialiser le tout
function init() {

// Récupérer le canvas à partir de son id
canvas = document.getElementById('game');

// Définir les dimensions de l'objet créé dans le canvas
height = canvas.height;
width = canvas.width;

// Une variable utilisée pour dessiner l'objet actuel
draw = canvas.getContext('2d');

// Nous voulons actualiser l'affichage toutes les 30 ms
setInterval(redraw, 30);

// Lorsqu'une touche est appuyée, lancer une fonction ;
// en lancer une autre lorsque la touche est relachée
document.onkeydown = canvasMove;
document.onkeyup = canvasStop;

}

Déplacer des rectangles dans un canvas peut être compliqué (le canvas étant dessiné autant de fois que demandé mais pas supprimé, vous vous retrouverez rapidement avec tout un tas de rectangles superposés), nous allons le redessiner toutes les 30 millisecondes. Cette fonction est appelée dans init().

// Effacer le rectangle quand nous devons le déplacer afin de pouvoir le redessiner.
function clear(c) {
c.clearRect(0, 0, width, height);
}

function redraw() {
clear(draw);
draw.fillStyle = 'rgba(0,0,0,0.5)';
draw.fillRect(left - right , down - up, '100', '100');
}

Ensuite, nous devons ajouter une fonctionnalité pour déplacer le carré. Nous voulons que deux touches fléchées puissent être utilisées ensemble, nous devons donc prévoir un fonctionnement un peu plus complexe qu'une simple instruction if(). Nous ajustons les variables de test des touches à true ou false selon les touches appuyées par l'utilisateur, de cette façon, nous pouvons avoir deux variables fixées à true en même temps, ce qui autorise les déplacements en diagonale.

function canvasMove(e) {

// Vérifie si la touche haut est appuyée
if(e.keyCode == '38') upcheck = true
// Sinon, vérifier si la touche gauche est appuyée et si haut est true
// Dans ce cas, mettre la flèche gauche à true
else if(e.keyCode == '37' && upcheck == true) leftcheck = true;
// else check if the right arrow is true, repeat.
else if(e.keyCode == '39' && upcheck == true) rightcheck = true;
// otherwise the up arrow is not being pressed, so it is false
else upcheck = false;

// Repeat for every arrow direction
if(e.keyCode == '40') downcheck = true;
else if(e.keyCode == '37' && downcheck == true) leftcheck = true;
else if(e.keyCode == '39' && downcheck == true) rightcheck = true;
else downcheck = false;

if(e.keyCode == '37') leftcheck = true;
else if(e.keyCode == '40' && leftcheck == true) downcheck = true;
else if(e.keyCode == '38' && leftcheck == true) upcheck = true;
else leftcheck = false;

if(e.keyCode == &amp;quot;39&amp;quot;) rightcheck = true;
else if(e.keyCode == '40' && rightcheck == true) downcheck = true;
else if(e.keyCode == '38' && rightcheck == true) upcheck = true;
else rightcheck = false;

// If the variables are true, increase the left and right movement accordingly.
// We also run the counting function, to keep track of total movement.
if(rightcheck == true) { left += 10; counting() };
if(leftcheck == true) { right += 10; counting() };
if(upcheck == true) { up += 10; counting(true) };
if(downcheck == true) { down += 10; counting(true) };

}

Ensuite, nous devons vérifier si l'utilisateur relâche une touche et affecter les variables correspondantes à false.

// Lorsque l'utilisateur relâche une touche, mettre la variable correspondante à false
function canvasStop(e) {

if(e.keyCode == '38') {
upcheck = false;
}
if(e.keyCode == '40') {
downcheck = false;
}
if(e.keyCode == '37') {
leftcheck = false;
}
if(e.keyCode == '39') {
rightcheck = false;
}

}

Pour finir, nous avons une fonction pour comptabiliser le tout.

function counting(y) {

if(y == true) {
document.getElementById('y').innerHTML = parseInt(document.getElementById('y').innerHTML) + 1;
}

else {
document.getElementById('x').innerHTML = parseInt(document.getElementById('x').innerHTML) + 1;
}
}

Et voilà ! Si vous souhaitez voir tout cela en action, faites un tour sur la page de démo ou téléchargez l'exemple complet.

Les entrées de souris

Maintenant, nous allons créer une interface de dessin et cela est étonnamment facile avec canvas. Comme d'habitude, nous allons commencer avec un peu de HTML.

<body onload="init();">
<div id="drawingcontainer">
<div class="text">
Dessinez ci-dessous !
</div>
<div id="options">
<input type="button" value="1px" onclick="changeSize(1);" />
<input type="button" value="2px" onclick="changeSize(2);" />
<input type="button" value="3px" onclick="changeSize(3);" />
<input type="button" value="5px" onclick="changeSize(5);" />
<input type="button" value="10px" onclick="changeSize(10);" />
<input type="button" value="15px" onclick="changeSize(20);" />

<input type="button" onclick="changeColor('#871de0');" class="purple" value="" />
<input type="button" onclick="changeColor('#eb159d');" class="pink" value="" />
<input type="button" onclick="changeColor('#c92626');" class="red" value="" />
<input type="button" onclick="changeColor('#db551b');" class="orange" value="" />
<input type="button" onclick="changeColor('#ddc41e');" class="yellow" value="" />
<input type="button" onclick="changeColor('#76b80f');" class="green" value="" />
<input type="button" onclick="changeColor('#1974b4');" class="blue" value="" />
<input type="button" onclick="changeColor('#000');" class="black" value="" />
<input type="button" onclick="changeColor('#FFF');" class="white" value="" />
</div>

<canvas width="690" height="500" id="drawing">
Your browser doesn't support canvas
</canvas>
</div>

</body>

Ensuite, définissons quelques variables et lançons la fonction init().

var canvas, draw;

var started = false;
var x, y;

function init() {

// Récupérer la zone de dessin
canvas = document.getElementById('drawing');
context = canvas.getContext('2d');

// Ajoutons des gestionnaires d'événements pour savoir ce qu'il se passe
// et lançons quelques fonctions associées.
canvas.addEventListener('mousemove', mousemovement, false);
canvas.addEventListener('mousedown', mouseclick, false);
canvas.addEventListener('mouseup', mouseunclick, false);

}

Maintenant, nous avons besoin de quelques fonctions pour effectuer des actions lorsque l'utilisateur clique, bouge la souris puis relâche la souris. Tout ce que font ces fonctions est de connaître la position de la souris et de tracer une ligne lorsque c'est utile.

function mouseclick() {
// Lorsque le clic est détecté, passe la variable started à true
// et déplace la position initiale de la souris
context.beginPath();
context.moveTo(x, y);
started = true;

}
// For getting the mouse position, basically. This gets the position
// of the canvas element, so we can use it to calculate the mouse
// position on the canvas
// Récupération de l'emplacement de la souris.
// On récupère la position de l'élément canvas pour pouvoir
// récupérer la position de la souris à l'intérieur du canvas.
function getOffset(e) {
var cx = 0;
var cy = 0;

while(e && !isNaN(e.offsetLeft) && !isNaN(e.offsetTop)) {
cx += e.offsetLeft - e.scrollLeft;
cy += e.offsetTop - e.scrollTop;
e = e.offsetParent;
}
return { top: cy, left: cx };
}

function mousemovement(e) {

// Récupérer la position de la souris

if(e.offsetX || e.offsetY) {
x = e.pageX - getOffset(document.getElementById('drawing')).left - window.pageXOffset;
y = e.pageY - getOffset(document.getElementById('drawing')).top - window.pageYOffset;
}
else if(e.layerX || e.layerY) {
x = (e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft)
- getOffset(document.getElementById('drawing')).left - window.pageXOffset;
y = (e.clientY + document.body.scrollTop + document.documentElement.scrollTop)
- getOffset(document.getElementById('drawing')).top;
}

// Si la variable started vaut true, alors tracer une ligne
if(started) {
contextMouse.lineTo(x, y);
contextMouse.stroke();

}

}

function mouseunclick() {
// Passer la variable started à false lorsque le bouton est relaché
if(started) {
started = false;
}

}

Enfin, nous avons besoin de deux fonctions supplémentaires pour modifier la largeur et la couleur du trait.

// Changer la taille
function changeSize(s) {
context.lineWidth = s;
}

// Changer la couleur
function changeColor(c) {
context.strokeStyle = c;
}

Et voilà ! Pour finir, ajoutons un peu de style en CSS.

body {
margin: 0;
padding:  0;
background: url('background.gif');
font-family: Arial, Helvetica, sans-serif;
}

canvas {
box-shadow: 0px 0px 30px rgba(0,0,0,0.3);
float: left;
border-radius: 6px;
display: block;
}

div {
font-family: 'Droid Sans', Helvetica, Arial, sans-serif;
font-size: 30px;
padding: 15px;
line-height: 30px;
}

#options {
float: left;
}

h3 {
float: left;
margin: 0;
}

div span {
float: left;
text-transform: uppercase;
padding: 0 20px 20px 20px;
font-size: 14px;
font-weight: bold;
}

div input {
float: left;
display: inline;
}

div input[type=range] {
position: relative;
top: 6px;
}

#options input[type=submit] {
border: 0;
border-radius: 4px;
margin-right: 10px;
width: 35px;
box-shadow: inset 0px 0px 10px rgba(0,0,0,0.2);
height: 35px;
position: relative;
cursor: pointer;
}

#options input[type=submit]:hover {
box-shadow: inset 0px 0px 10px rgba(0,0,0,0.5);
}

#options input[type=submit]:active {
top: 2px;
}

.purple { background: #871de0; }
.pink { background: #eb159d; }
.red { background: #c92626; }
.orange { background: #db551b; }
.yellow { background: #ddc41e; }
.green { background: #76b80f; }
.blue { background: #1974b4; }
.black { background: #000; }
.white { background: #fff; }

#drawingcontainer {
width: 710px;
margin: 0px auto;
}

J'ai mis en place une page de démonstration pour tester tout cela. Regardez la page de démonstration ou téléchargez l'archive si vous souhaitez modifier le script.

Remerciements

Cet article a été traduit avec l'aimable autorisation de inserthtml. L'article original : A Look at HTML5 Canvas Interactivity peut être vu sur le site de inserthtml.

Nous tenons à remercier FirePrawn et ClaudeLELOUP pour leur relecture attentive de cet article.