Comme nous l'avons vu précédemment, il existe deux grands types de formats d'images:

  • les images matricielles,
  • et les images vectorielles.

Ces deux types d'images peuvent être intégrées dans une page web grâce à la balise <img>, mais elles peuvent être aussi codées directement dans la page grâce aux balises <svg> et <canvas>.

Nous nous intéressons ici au dessin matriciel dans la balise canvas.

Html5 canvas logo

Comment dessiner dans le canvas?

La balise <canvas> qui fait partie de la spécification HTML5 du W3C permet d'effectuer des rendus dynamiques d'images bitmap dans le navigateur grâce à des scripts javascript.

Comme souvent dans les images numériques, le système de coordonnée est défini avec un axe des ordonnées (y) orienté vers le bas.

système d'axes d'une image numérique

Code html

Pour utiliser les zones de dessin canvas, on ajoute un élément <canvas> vide dans le corps du document avec un id afin de pouvoir le modifier à partir du javascript.

<canvas id="mon-canvas" width="500" height="400">
  <!-- Le texte suivant sera affiché si la balise canvas n'est pas supporté par son navigateur -->
  Votre navigateur ne  supporte pas la balise HTML5 Canvas.
</canvas>

Code javascript

Nous allons maintenant dessiner dans ce canvas grâce à un script javascript qu'on intégrera comme n'importe quel code javascript(voir Ajouter du dynamisme avec javascript)

Pour cela, on sélectionne la balise canvas, puis on se place dans un contexte de canvas à deux dimensions avec la méthode getContext('2d')

// initialisation du contexte
var theCanvas = document.getElementById('mon-canvas')
var context = theCanvas.getContext('2d')

Un fois qu'on a récupéré le contexte, on dessine dedans avec des fonctions de dessin telles que:

  • strokeRect: pour dessiner un rectangle,
  • fillRect: pour colorier un rectangle,
  • filltext: pour écrire du texte...

La liste complète des fonctions de dessin peut-être trouvée sur le tutoriel canvas sur MDN.

Voici par exemple quelques instructions qui permettent de dessiner un rectangle avec écrit au milieu: Bienvenue dans le monde du canvas.

Bienvenue dans le monde du canvas

// fond coloré
context.fillStyle = '#ffffaa'
context.fillRect(0, 0, 400, 300)
// texte centré
context.fillStyle = '#333333'
context.font = '20px Serif'
context.textAlign = 'center'
context.fillText('Bienvenue dans le monde du canvas', 200, 150)

// boite englobante
context.strokeStyle = '#000000'
context.strokeRect(5, 5, 390, 290)

Exemple interactif

Vous pouvez vous familiariser avec ces méthodes dans l'exemple interactif ci-dessous.

Comment améliorer l'ergonomie du code avec des fonctions?

Très souvent on englobe les instructions de dessin au sein de fonctions, pour mieux organiser le code, le rendre plus lisible et plus ergonomique.

En javascript, les fonctions se définissent à l'aide du mot-clef function, et sont ensuite appelées en écrivant le nom de la fonction suivies de parenthèses contenant éventuellement les arguments passés à la fonction.

// Définition de la fonction
function dessineUnCarré(x, y, cote, couleur) {
    context.fillStyle = couleur
    context.fillRect(x, y, cote, cote)
}

// appel de la fonction avec les arguments
// x = 10
// y = 100
// cote = 50
dessineUnCarré(10, 100, 50)

Voici un code html complet qui dessine un smiley dans le canvas:

<!DOCTYPE html>
<html lang="fr">
  <head>
    <meta charset="utf-8" />
    <title>Dessin en canvas</title>
  </head>

  <body>
    <canvas id="mon-canvas" width="400" height="300">
      Votre navigateur ne supporte pas la balise HTML5 Canvas.
    </canvas>

    <script>
      var theCanvas = document.getElementById('mon-canvas')
      var ctx = theCanvas.getContext('2d')

      // background
      function drawBackground() {
        ctx.fillStyle = '#ffffaa'
        ctx.fillRect(0, 0, 400, 300)

        // box
        ctx.strokeStyle = '#000000'
        ctx.strokeRect(5, 5, 390, 290)
      }

      function drawSmiley(x, y) {
        // smiley
        ctx.beginPath()
        ctx.arc(x, y, 50, 0, Math.PI * 2, true) // Tête
        ctx.fillStyle = '#FFFF00'
        ctx.fill() // Colorier la tête en jaune
        ctx.moveTo(x + 35, y)
        ctx.arc(x, y, 35, 0, Math.PI, false) // Bouche
        ctx.moveTo(x - 10, y - 10)
        ctx.arc(x - 15, y - 10, 5, 0, Math.PI * 2, true) // Oeil gauche
        ctx.moveTo(x + 20, y - 10)
        ctx.arc(x + 15, y - 10, 5, 0, Math.PI * 2, true) // Oeil droit

        ctx.lineWidth = 5
        ctx.stroke()
      }

      // appel des fonctions pour dessiner dans le canvas
      //
      // On dessine le fond
      drawBackground()
      // On dessine le smiley en passant en arguments de la fonctions
      //les coordonnées x et y auxquelles on veut le dessiner
      drawSmiley(200, 150)
    </script>
  </body>
</html>

RENDU

Rendu de l'élément canvas

Essayez modifier certains des paramètres du code pour vous familiariser avec sa syntaxe, puis ajouter des éléments en utilisant cette page de référence de w3schools

Comment créer des animations?

Pou animer un dessin canvas, nous allons utiliser la méthode window.requestAnimationFrame(), cette méthode permet d'éxecuter une fonction à chaque affichage de la fenêtre du navigateur(soit environ 60 images/seconde).

On crée ainsi une fonction anime() qui s'appelle elle-même à chaque rafraichissement de l'affichage.

// Création de la fonction
function anime() {
  requestAnimationFrame(anime)
  // Commandes de dessin
}

// Appel de la fonction pour lancer l'animation
anime()

Création d'un prototype Smiley

Nous allons créer un objet prototype Smiley qui stockera à la fois des variables de coordonées, de vitesses du Smiley, mais également des méthodes qui lui permettent de se déplacer, de se dessiner.

function Smiley(x, y, vx, vy) {
    // initialisation de l'objet Smiley avec les coordonnées et vitesses
    this.x = x
    this.y = y
    this.vx = vx
    this.vy = vy
    
    // méthode de dessin du smiley
    this.dessineToi = function() {
        // code semblable à celui vu précédemment dans la fonction drawSmiley
        ...
    };

    // modifie les coordonnées du smiley pour le prochain rafrachissement
    this.deplaceToi = function() {
        
        this.x += this.vx
        this.y += this.vy
    }
}

Après initialisation du Smiley au début de l'animation, on pourra alors utiliser ce prototype la méthode deplaceToi de l'objet Smiley à chaque rafraichissement de la page dans la fonction anime.

Initilisation de l'objet Smiley

On initialise l'objet Smiley au milieu de l'écran avec des vitesses aléatoires.

var smiley = new Smiley(
  width / 2, // x
  height / 2, // y
  10 * Math.random() - 5, // vx
  10 * Math.random() - 5  // vy
)

Animation

On ajoute les instructions à la fonction anime.

function anime() {
  // On dessine le fond du canvas
  dessineFond()

  // On déplace le smiley
  smiley.deplaceToi()

  // On dessine le smiley
  smiley.dessineToi()

  // On demande une nouvelle frame d'animation
  window.requestAnimationFrame(anime)
}

Il ne reste maintenant plus qu'à gérer les collisions avec les parois pour modifier les vitesses du Smiley en cas de rebond, c'est ce qui est fait dans la fonction checkWallCollision.

Exemple interactif

Concours de monstre animé

Voici un concours proposé à ses étudiants par Michel Buffa: Animer un monstre et le rendre le plus... ce que vous voulez. Un petit exemple pour commencer.

http://jsbin.com/garagowe/14/edit

A votre tour.