publié le jeu. 29 mars 2018

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

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.

Dessin matriciel dans le canvas

Html5 canvas logo

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 bitmaps, le système de coordonnée est défini avec une origine en haut à gauche de l'image.

Votre navigateur ne supporte pas la balise HTML5 Canvas.

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="monCanvas" width="500" height="400">
  <!-- Le texte suivant sera affiché si la balise cancas 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éléctionne la balise canvas, puis on se place dans un contexte de canvas à deux dimensions avec la méthode getContext('2d')

var theCanvas = document.getElementById("monCanvas");
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:

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 mileu: Bienvenue dans le monde du canvas.

//background
context.fillStyle = "#ffffaa";
context.fillRect(0, 0, 500, 300);

//text
context.fillStyle = "#333333";
context.font = "20px Sans-Serif";
context.textBaseline = "top";
context.fillText("Bienvenue dans le monde du canvas", 195, 80);

//box
context.strokeStyle = "#000000";
context.strokeRect(5, 5, 490, 290);

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.

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>
        <script type="text/javascript" charset="utf-8">
            window.onload = function() {

                var theCanvas = document.getElementById("monCanvas");
                var ctx = theCanvas.getContext("2d");

                function drawScreen() {
                    //background
                    ctx.fillStyle = "#ffffaa";
                    ctx.fillRect(0, 0, 500, 400);

                    //text
                    ctx.fillStyle = "#333333";
                    ctx.font = "18px Sans-Serif";
                    ctx.textBaseline = "top";
                    ctx.fillText("Bienvenue dans le monde du canvas", 95, 110);
                    //box
                    ctx.strokeStyle = "#000000";
                    ctx.strokeRect(5, 5, 490, 390);

                    //smiley
                    ctx.beginPath();
                    ctx.arc(250, 200, 50, 0, Math.PI * 2, true); // Tête
                    ctx.fillStyle = "#FFFF00";
                    ctx.fill(); // Colorier la tête en jaune
                    ctx.moveTo(285, 200);
                    ctx.arc(250, 200, 35, 0, Math.PI, false); // Bouche
                    ctx.moveTo(240, 190);
                    ctx.arc(235, 190, 5, 0, Math.PI * 2, true); // Oeil gauche
                    ctx.moveTo(270, 190);
                    ctx.arc(265, 190, 5, 0, Math.PI * 2, true); // Oeil droit

                    ctx.lineWidth = 5;
                    ctx.stroke();

                }

                drawScreen();

            }
        </script>
    </head>

    <body>

        <canvas id="monCanvas" width="500" height="400">
            Votre navigateur ne supporte pas la balise HTML5 Canvas.
        </canvas>

    </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

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

Ensuite pour que l'affichage soit différent à chaque rafraichissement il faut que les commandes dessin utilisent des variables de coordonnées.

Déplacer un objet et détecter les bords pour qu'il rebondisse

Voici par exemple comment on peut dessiner le même smiley que tout à l'heure, mais à des coordonnées x et y, données en paramètres de la fonction. Grâce à cette fonction il suffira d'éxecuter Smiley(60,70) pour dessiner un smiley centré aux coordonnées x = 60 et y = 70.

function Smiley(x, y) {
    this.x = x;
    this.y = y;

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

        ctx.lineWidth = 5;
        ctx.stroke();
    };

On crée ensuite une méthode deplaceToi à l'objet Smiley qui ajoute vx à la coordonnée x et vy à la coordonnée y à chaque image.

Puis une fonction checkWallCollision() qui vérifie que le smiley ne touche pas les bords de l'écran, et qui inverse une des composante de la vitesse lorsque le smiley touche une paroi horizontale ou verticale.

Code complet

<!doctype html>
<html lang="fr">

    <head>
        <meta charset="utf-8">
        <title>Dessin en canvas</title>
        <script type="text/javascript" charset="utf-8">
            window.onload = function() {
                // Variable qui correspond au canvas
                var monCanvas = document.getElementById("monCanvas");
                // Dimensions du canvas
                var width = monCanvas.width;
                var height = monCanvas.height;
                // contexte graphique 2D
                var ctx = monCanvas.getContext('2d');

                // Inititialisation des coordonnées et vitesses du smiley
                var smiley = new Smiley(width / 2, height / 2, (10 * Math.random()) - 5, (10 * Math.random()) - 5);

                // Lancement de l'animation
                anime();

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

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

                    // 3) On regarde si le smiley touche un mur
                    checkWallCollision(smiley);

                    // 3) On dessine le smiley
                    smiley.dessineToi();

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

                function dessineFond() {
                    // On efface l'écran
                    ctx.clearRect(0, 0, monCanvas.width, monCanvas.height);

                    //background
                    ctx.fillStyle = "#ffffcc";
                    ctx.fillRect(0, 0, monCanvas.width, monCanvas.height);

                    //box
                    ctx.strokeStyle = "#000000";
                    ctx.strokeRect(5, 5, 490, 390);
                }

                // fonction smiley qui stocke ses coordonnées et sa vitesse
                // et qui possède deux méthodes pour se dessiner et se déplacer

                function Smiley(x, y, vx, vy) {
                    this.x = x;
                    this.y = y;
                    this.vx = vx;
                    this.vy = vy;
                    this.radius = 50;

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

                        ctx.lineWidth = 5;
                        ctx.stroke();
                    };

                    this.deplaceToi = function() {

                        this.x += this.vx;
                        this.y += this.vy;
                    };
                }

                function checkWallCollision(objet) {
                    if (objet.x < objet.radius) {
                        objet.x = objet.radius;
                        objet.vx *= -1;
                    }
                    if (objet.x > width - (objet.radius)) {
                        objet.x = width - (objet.radius);
                        objet.vx *= -1;
                    }
                    if (objet.y < objet.radius) {
                        objet.y = objet.radius;
                        objet.vy *= -1;
                    }
                    if (objet.y > height - (objet.radius)) {
                        objet.y = height - (objet.radius);
                        objet.vy *= -1;
                    }
                }


            }
        </script>
    </head>

    <body>

        <canvas id="monCanvas" width="500" height="400">
            Votre navigateur ne supporte pas la balise HTML5 Canvas.
        </canvas>

    </body>

</html>

RENDU

Votre navigateur ne supporte pas la balise HTML5 Canvas.

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.

Matière: isn Mots-clés: html5 canvas