Mozilla's getting a new look. What do you think? https://mzl.la/brandsurvey

Animations basiques

Cette traduction est incomplète. Aidez à traduire cet article depuis l'anglais.

Depuis qu'on peut dessiner en Javascript avec les <canvas>, il est très simple de créer des animations interactives. Ce chapitre décrit comment créer quelques animations basiques.

La plus grosse limitation est sans doute que, une fois qu'une forme est dessinée, elle reste telle quelle. Si on a besoin de la déplacer, il faut la redessiner avec que ce qui a été dessiné avant. De plus, cela peut prendre beaucoup de temps de redessiner des images complexes. Les performances dépendront alors beaucoup de la vitesse de l'ordinateur qui s'occupe de cet affichage.

Les étapes d'une animation basique

Voici les étapes à suivre à chaque image dessinée (frame) :

  1. Effacer le canvas
    À partir du moment où vous remplissez le canvas (comme avec un motif de fond), vous devrez effacer toutes les formes dessinées. La méthode la plus simple est d'utiliser clearRect().
  2. Enregistrer l'état du canvas
    Si vous changez des configurations (comme le style, les transformations, etc.) qui affectent l'état du canvas et que vous voulez vous assurer que l'état original est utilisé chaque fois que le canvas est redessiné, vous devez enregistrer l'état original du canvas.
  3. Dessiner les formes animées
    On effectue toutes les opérations de rendu pour l'image actuelle.
  4. Réstaurer l'état du canvas
    Si l'état du canvas a été sauvegardé, il faut le restaurer avant un nouveau rendu.

Contrôler une animation

Les formes sont dessinées en utilisant directement les méthodes du canvas ou en appelant des fonctions personnalisées. Dans des conditions normales, on voit le résultat quand le script a terminé son exécution. Cela signifie qu'il n'est pas possible de créer une animation dans une boucle for.

Il faut donc utiliser des fonctions de dessin lancées avec une période donnée. Il en existe aujourd'hui trois.

Mise à jour planifiée

Les fonctions window.setInterval(), window.setTimeout(), et window.requestAnimationFrame() peuvent être utilisées :

setInterval(function, delay)
Lance la fonction définie par function chaque delay millisecondes.
setTimeout(function, delay)
Exécute la fonction définie par function dans delay millisecondes.
requestAnimationFrame(callback)
Informe le navigateur que l'on veut afficher une animation et lui demande d'appeler la fonction callback pour mettre à jour cette animation avant que l'écran soit redessiné.

Si vous n'avez pas besoin d'interaction utilisateur, vous pouvez utiliser la fonction setInterval() qui va exécuter périodiquement votre code. Si on veut faire un jeu, on peut utiliser les événements du clavier et de la souris pour contrôler l'animation et utiliser setTimeout(). En créer des EventListener, on récupère chaque interaction et on exécute nos fonctions d'animation.

In the examples below, we'll use the window.requestAnimationFrame() method to control the animation. The requestAnimationFrame method provides a smoother and more efficient way for animating by calling the animation frame when the system is ready to paint the frame. The number of callbacks is usually 60 times per second and may be reduced to a lower rate when running in background tabs. For more information about the animation loop, especially for games, see the article Anatomy of a video game in our Game development zone.

Un système solaire animé

Cette exemple anime un petit modèle de notre système solaire.

var sun = new Image();
var moon = new Image();
var earth = new Image();
function init(){
  sun.src = 'https://mdn.mozillademos.org/files/1456/Canvas_sun.png';
  moon.src = 'https://mdn.mozillademos.org/files/1443/Canvas_moon.png';
  earth.src = 'https://mdn.mozillademos.org/files/1429/Canvas_earth.png';
  window.requestAnimationFrame(draw);
}

function draw() {
  var ctx = document.getElementById('canvas').getContext('2d');

  ctx.globalCompositeOperation = 'destination-over';
  ctx.clearRect(0,0,300,300); // effacer le canvas

  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); // Earth orbit
  ctx.stroke();
 
  ctx.drawImage(sun,0,0,300,300);

  window.requestAnimationFrame(draw);
}

init();

ScreenshotLive sample

Une horloge animée

Cette exemple dessine une horloge animée qui affiche l'heure actuelle.

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";

  // Marquage des heures
  ctx.save();
  for (var i=0;i<12;i++){
    ctx.beginPath();
    ctx.rotate(Math.PI/6);
    ctx.moveTo(100,0);
    ctx.lineTo(120,0);
    ctx.stroke();
  }
  ctx.restore();

  // Marquage des minutes
  ctx.save();
  ctx.lineWidth = 5;
  for (i=0;i<60;i++){
    if (i%5!=0) {
      ctx.beginPath();
      ctx.moveTo(117,0);
      ctx.lineTo(120,0);
      ctx.stroke();
    }
    ctx.rotate(Math.PI/30);
  }
  ctx.restore();
 
  var sec = now.getSeconds();
  var min = now.getMinutes();
  var hr  = now.getHours();
  hr = hr>=12 ? hr-12 : hr;

  ctx.fillStyle = "black";

  // Aiguille 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();

  // Aiguille 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();
 
  // Aiguille 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 = "rgba(0,0,0,0)";
  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();

  window.requestAnimationFrame(clock);
}

window.requestAnimationFrame(clock);

ScreenshotLive sample

A looping panorama

In this example, a panorama is scrolled left-to-right. We're using an image of Yosemite National Park we took from Wikipedia, but you could use any image that's larger than the canvas.

var img = new Image();

// User Variables - customize these to change the image being scrolled, its
// direction, and the speed.

img.src = 'https://mdn.mozillademos.org/files/4553/Capitan_Meadows,_Yosemite_National_Park.jpg';
var CanvasXSize = 800;
var CanvasYSize = 200;
var speed = 30; //lower is faster
var scale = 1.05;
var y = -4.5; //vertical offset

// Main program

var dx = 0.75;
var imgW;
var imgH;
var x = 0;
var clearX;
var clearY;
var ctx;

img.onload = function() {
    imgW = img.width*scale;
    imgH = img.height*scale;
    if (imgW > CanvasXSize) { x = CanvasXSize-imgW; } // image larger than canvas
    if (imgW > CanvasXSize) { clearX = imgW; } // image larger than canvas
    else { clearX = CanvasXSize; }
    if (imgH > CanvasYSize) { clearY = imgH; } // image larger than canvas
    else { clearY = CanvasYSize; }
    //Get Canvas Element
    ctx = document.getElementById('canvas').getContext('2d');
    //Set Refresh Rate
    return setInterval(draw, speed);
}

function draw() {
    //Clear Canvas
    ctx.clearRect(0,0,clearX,clearY);
    //If image is <= Canvas Size
    if (imgW <= CanvasXSize) {
        //reset, start from beginning
        if (x > (CanvasXSize)) { x = 0; }
        //draw aditional image
        if (x > (CanvasXSize-imgW)) { ctx.drawImage(img,x-CanvasXSize+1,y,imgW,imgH); }
    }
    //If image is > Canvas Size
    else {
        //reset, start from beginning
        if (x > (CanvasXSize)) { x = CanvasXSize-imgW; }
        //draw aditional image
        if (x > (CanvasXSize-imgW)) { ctx.drawImage(img,x-imgW+1,y,imgW,imgH); }
    }
    //draw image
    ctx.drawImage(img,x,y,imgW,imgH);
    //amount to move
    x += dx;
}

Below is the <canvas> in which the image is scrolled. Note that the width and height specified here must match the values of the CanvasXZSize and CanvasYSize variables in the JavaScript code.

<canvas id="canvas" width="800" height="200"></canvas>

Other examples

A basic ray-caster
A good example of how to do animations using keyboard controls.
Advanced animations
We will have a look at some advanced animation techniques and physics in the next chapter.

Étiquettes et contributeurs liés au document

 Contributeurs à cette page : lumiru
 Dernière mise à jour par : lumiru,