Tutoriel canvas:Animations basiques
Un article de MDC.
Sommaire |
Comme on utilise des scripts pour contrôler les éléments canvas, il est également très facile de créer des animations (interactives). Malheureusement, l'élément canvas n'a pas été conçu pour être utilisé de cette façon (au contraire de Flash), il y a donc certaines limitations.
La plus importante est qu'une fois qu'une forme a été dessinée, elle le reste. Si on veut la faire bouger, il faut la redessiner ainsi que tout ce qui avait été dessiné avant elle. Redessiner des formes complexes prend beaucoup de temps et les performances dépendent fortement de la vitesse de l'ordinateur sur lequel on se trouve.
[modifier] Étapes de base d'une animation
Lorsqu'on dessine une image complète faisant partie d'une animation, il y a toujours un nombre défini d'étapes nécessaires.
- Effacer le canevas
À moins que les formes que vous allez dessiner remplissent toute la surface du canevas (par exemple une image de fond), il est nécessaire d'effacer toute forme qui peut avoir été dessinée précédemment. La manière la plus simple de le faire est d'utiliser la méthodeclearRect. - Enregistrer l'état du canevas
Si vous changez des réglages (styles, transformations, etc.) qui affectent l'état du canevas et voulez vous assurer que l'état original du canevas est utilisé à chaque nouvelle image, il est nécessaire de l'enregistrer. - Dessiner les formes animées
L'étape où l'image complète est réellement dessinée. - Restaurer l'état du canevas
Si l'état a été enregistré, il faudra le restaurer avant de dessiner une nouvelle image.
[modifier] Contrôle d'une animation
Les formes sont dessinées sur le canevas directement à l'aide des méthodes canvas, ou en appelant des fonctions personnalisées. Dans des circonstances normales, le résultat apparaît sur le canevas uniquement lorsque le script a terminé son exécution. Par exemple, il n'est pas possible de faire une animation au sein d'une boucle for.
Il est nécessaire de disposer d'une manière d'exécuter nos fonctions de dessin sur une période de temps. Il existe deux façons de contrôler une animation de la sorte. Premièrement, on peut utiliser les fonctions setInterval et setTimeout pour appeler une fonction spécifique sur une période de temps définie.
setInterval('animerImage()', 500);
setTimeout('animerImage()', 500);
Si vous ne voulez aucune interaction avec l'utilisateur, il est préférable d'utiliser la fonction setInterval qui exécute le code fourni de manière répétée. Dans l'exemple ci-dessus, la fonction animateShape est exécutée toutes les 500 milisecondes (chaque demi-seconde).
La fonction setTimeout n'est quant à elle exécutée qu'une fois après l'intervalle de temps donné.
La seconde méthode qu'on peut utiliser pour contrôler une animation est l'intervention de l'utilisateur. Si l'on veut réaliser un jeu, on peut utiliser les évènements souris ou du clavier pour contrôler l'animation. En définissant des écouteurs d'évènements (eventListeners), on intercepte les interventions de l'utilisateur et on peut exécuter nos fonctions d'animation.
Dans les exemples ci-dessous, c'est la première méthode de contrôle qui est utilisée. En bas de la page, vous trouverez des liens vers des exemples utilisant la seconde.
[modifier] Un premier exemple d'animation
Dans cet exemple, on anime une mini simulation de notre système solaire.
var sun = new Image();
var moon = new Image();
var earth = new Image();
function init() {
sun.src = 'images/sun.png';
moon.src = 'images/moon.png';
earth.src = 'images/earth.png';
setInterval('draw()',100);
}
function draw() {
var ctx = document.getElementById('canvas').getContext('2d');
ctx.globalCompositeOperation = 'destination-over';
ctx.clearRect(0, 0, 300, 300); // efface le canevas
ctx.fillStyle = 'rgba(0,0,0,0.4)';
ctx.strokeStyle = 'rgba(0,153,255,0.4)';
ctx.save();
ctx.translate(150, 150);
// Terre
var time = new Date();
ctx.rotate( ((2*Math.PI)/60)*time.getSeconds() + ((2*Math.PI)/60000)*time.getMilliseconds() );
ctx.translate(105,0);
ctx.fillRect(0, -12, 50, 24); // Ombre
ctx.drawImage(earth, -12, -12);
// Lune
ctx.save();
ctx.rotate( ((2*Math.PI)/6)*time.getSeconds() + ((2*Math.PI)/6000)*time.getMilliseconds() );
ctx.translate(0, 28.5);
ctx.drawImage(moon, -3.5, -3.5);
ctx.restore();
ctx.restore();
ctx.beginPath();
ctx.arc(150, 150, 105, 0, Math.PI*2, false); // orbite terrestre
ctx.stroke();
ctx.drawImage(sun, 0, 0, 300, 300);
}
[modifier] Un second exemple d'animation
function init() {
clock();
setInterval('clock()', 1000);
}
function clock() {
var now = new Date();
var ctx = document.getElementById('canvas').getContext('2d');
ctx.save();
ctx.clearRect(0, 0, 150, 150);
ctx.translate(75, 75);
ctx.scale(0.4, 0.4);
ctx.rotate(-Math.PI/2);
ctx.strokeStyle = "black";
ctx.fillStyle = "white";
ctx.lineWidth = 8;
ctx.lineCap = "round";
// Marques des heures
ctx.save();
ctx.beginPath();
for (i = 0; i < 12; i++) {
ctx.rotate(Math.PI/6);
ctx.moveTo(100, 0);
ctx.lineTo(120, 0);
}
ctx.stroke();
ctx.restore();
// Marques des minutes
ctx.save();
ctx.lineWidth = 5;
ctx.beginPath();
for (i = 0; i < 60; i++) {
if (i%5 != 0) {
ctx.moveTo(117, 0);
ctx.lineTo(120, 0);
}
ctx.rotate(Math.PI/30);
}
ctx.stroke();
ctx.restore();
var sec = now.getSeconds();
var min = now.getMinutes();
var hr = now.getHours();
hr = (hr >= 12) ? hr-12 : hr;
ctx.fillStyle = "black";
// Dessin des heures
ctx.save();
ctx.rotate( hr*(Math.PI/6) + (Math.PI/360)*min + (Math.PI/21600)*sec )
ctx.lineWidth = 14;
ctx.beginPath();
ctx.moveTo(-20, 0);
ctx.lineTo(80, 0);
ctx.stroke();
ctx.restore();
// Dessin des minutes
ctx.save();
ctx.rotate( (Math.PI/30)*min + (Math.PI/1800)*sec )
ctx.lineWidth = 10;
ctx.beginPath();
ctx.moveTo(-28, 0);
ctx.lineTo(112, 0);
ctx.stroke();
ctx.restore();
// Dessin des secondes
ctx.save();
ctx.rotate(sec * Math.PI/30);
ctx.strokeStyle = "#D40000";
ctx.fillStyle = "#D40000";
ctx.lineWidth = 6;
ctx.beginPath();
ctx.moveTo(-30, 0);
ctx.lineTo(83, 0);
ctx.stroke();
ctx.beginPath();
ctx.arc(0, 0, 10, 0, Math.PI*2, true);
ctx.fill();
ctx.beginPath();
ctx.arc(95, 0, 10, 0, Math.PI*2, true);
ctx.stroke();
ctx.fillStyle = "#555";
ctx.arc(0, 0, 3, 0, Math.PI*2, true);
ctx.fill();
ctx.restore();
ctx.beginPath();
ctx.lineWidth = 14;
ctx.strokeStyle = '#325FA2';
ctx.arc(0, 0, 142, 0, Math.PI*2, true);
ctx.stroke();
ctx.restore();
}
[modifier] Autres exemples
- Canvascape
Un jeu d'aventures en 3D (vue à la première personne). - Un raycaster basique
Un bon exemple d'animation utilisant le contrôle au clavier. - canvas adventure
Un autre exemple utilisant le contrôle au clavier. - Un Blob interactif
Amusez-vous avec le blob. - Naviguer parmi les étoiles
Naviguer parmi les étoiles, les cercles ou les carrés.

