Initiation aux animations

Maintenant vous savez modifier le DOM de la page vous êtes capables de réaliser de petites animations voire de petits jeux sympathiques dans une page web ...

Pour tester tous les exemples de ce chapitre il faut afficher la console JavaScript !!!

Pour afficher la console JS sous Chrome produisez la commande :
Personnaliser Chrome (trois points verticaux en haut à droite) / plus d'outils / outils de développement / onglet "console"

Pour afficher la console "web" sous Firefox la commande est :
Ouvrir menu (trois traits horizontaux) / outils de développement / console web

La problématique

Une animation 2D basique c'est une zone d'animation (une balise DIV) avec en "background" une image faisant fonction de décor.
A cela ajouter des "sprites" ou lutin c'est à dire des personnages sous forme d'images GIF (animées ou pas).

Dans le cadre du responsive web design la largeur de la zone d'animation ne doit pas être exprimée en pixels mais en pourcentages ! Donc concernant les "sprites" positionnés en absolu dans la zone d'animation, les valeurs de la propriété left (ou right) doivent aussi être exprimées %.
Pour que l'image de fond s'adapte à la zone il faut utiliser la nouvelle propriété CSS background-size : cover

Exemple

... <div style = "display : block ; width : 100% ; height : 400px ; position : relative ; background : url(../images/fond3.jpg) ; margin : auto ; background-size : cover ; " > <img src ='../images/requin.gif' style = "position : absolute ; top : 50px; left : 10% ; " > </div> <script> // variables globales var zone = document.querySelector('div'); var requin = document.querySelector('img'); var X,Y,x,y ; // récupération dimensions zone et position du sprite : première solution X = zone.style.width; Y =zone.style.height; x = requin.style.left; y = requin.style.top ; affichage(); // récupération dimensions zone et position du sprite : deuxièm solution X = getComputedStyle(zone).width; Y = getComputedStyle(zone).height; x = getComputedStyle(requin).left; y = getComputedStyle(requin).top; affichage(); function affichage() { console.log("largeur zone :" + X + " " + typeof(X)); console.log("hauteur zone :" + Y + " " + typeof(Y)); console.log("positionX du requin " + x + " " + typeof(x)); console.log("positionY du requin " + y + " " + typeof(y)); } </script> ...

Notez bien que la largeur de la zone d'animation est exprimée en pourcentage : 100% (du conteneur).

Test


Essayez ce code !

Ces deux techniques ne donnent pas les mêmes résultats pour X et x !
Dans les deux cas les valeurs retournées sont de type string mais dans le premier cas X & x sont exprimées en "%" tandis que dans le second cas X & x sont exprimés en "px".
La méthode getComputedStyle fait en effet une conversion. Sur un grand écran la largeur du conteneur de DIV (BODY) fait 900px donc la méthode retourne "900px" (100% de 900).
Réduisez la largeur de la fenêtre et actualiser la page ! Vous voyez que le résultat n'est plus le même avec la deuxième méthode (alors que la première méthode affiche toujours une largeur de 100%).

Animation contrôlée par l'internaute

Maintenant que l'on connait le type et le format des données contenus dans les variables X,Y,x,y on peut passer à l'animation.

Dans l'exemple ci-dessous l'internaute déplace le requin dans un beau décor grâce à un clavier tactile.

Le code correspondant

... <style> th, img {border : none ; } </style> <div id = 'decor'style = "display : block ; width : 100% ; height : 400px ; position : relative ; background : url(../images/fond3.jpg) ; margin : auto ; background-size : cover ; " > <img id ='requin' src ='../images/requin.gif' style = "position : absolute ; top : 50px; left : 10% ; " > </div> <table> <caption>Déplacer le squale</caption> <tr><th></th><th><button id ='haut' >&uarr;</button></th><th></th></tr> <tr><th><button id ='gauche'>&larr;</button></th><th></th> <th><button id ='droite'>&rarr;</button></th></tr> <tr><th></th><th><button id = 'bas'>&darr;</button></th><th></th></tr> </table> <script> var requin = document.querySelector('#requin') ; x = requin.style.left; y = requin.style.top; console.log(x); console.log(y); document.querySelector('#droite').onclick = function() { x = parseInt(x) ; x+=3 ; x = x +'%' ; requin.style.left = x ; finfo();} document.querySelector('#gauche').onclick = function() { x = parseInt(x) ; x -=3 ; x = x +'%' ; requin.style.left = x ; finfo();} document.querySelector('#haut').onclick = function() { y = parseInt(y) ; y-=20; y = y +'px' ; requin.style.top = y ; finfo();} document.querySelector('#bas').onclick = function() { y = parseInt(y) ; y+=20; y = y +'px' ; requin.style.top = y ;finfo();} function finfo() { console.log("positionX du requin " + x ); console.log("positionY du requin " + y ); } </script> ...

Commentaire du code

Du CSS et du HTML : La zone d'animation fait 100% par 400px.
Déplacement du "sprite" par un clavier tactile avec quatre touches (flèches). Le clavier tactile est un tableau de 9 cellules (3 par 3) donc cinq cellules vides et quatre cellules contenant un bouton. Chaque bouton affiche une flèche (emploi des entités de caractère) et chaque bouton a un ID.

Du JS : Comme j'utilise la syntaxe élément.style.left pour récupérer la positionX du requin la nouvelle valeur de left doit être une chaine telle "20%" ! Ici la variation est de 3% horizontalement (et 20px verticalement).
Si j'avais utilisé la deuxième syntaxe la nouvelle valeur de left devrait être une chaine telle "20px".

Si clic sur l'un des boutons appel d'une des quatre fonctions anonymes.
Dans chaque fonction il faut convertir le contenu de x (ou y) en un entier (se débarrasser de "px" ou "%") puis il faut faire incrémenter (ou décrémenter) x ou y puis il faut rajouter "px" à x et "%" à y et enfin il faut modifier la valeur des propriétés left & top.
Chaque fonction anonyme appelle la fonction finfo() qui indique la nouvelle position du requin dans le décor (ou en dehors ...).

Le requin peut sortir du décor car ici les "effets de bord" ne sont pas gérés.
Essayez !

Exercice

Vérifions de suite si vous avez bien compris la subtilité que je viens d'évoquer ...
Ci-dessous variante de l'animation précédente.

Déplacer le squale

C'est la même animation sauf je récupère la position initiale du requin avec la méthode getComputedStyle.

Concevez le script ! ; le code CSS & HTML est identique à la première version.
Je vous communique le début du script !

var requin = document.querySelector('#requin') ; x = getComputedStyle(requin).left; y = getComputedStyle(requin).top;

Le déplacement doit être de 20 pixels horizontalement ou verticalement à chaque clic.

Animation automatique

Un plongeur se déplace automatiquement dans un beau décor corallien.

Le code correspondant

... <div id = 'decor'style = "display : block ; width : 600px ; height : 400px ; position : relative ; background : url(../images/fond3.jpg) ; margin : auto ; background-size : cover; " > <img id ='plongeur' src ='../images/plongeur3.gif' style = "position : absolute ; top : 350px; left : 500px ; " > </div> <button>Arrêter animation</button> <script> var zone = document.querySelector('div'); var plongeur = document.querySelector('#plongeur') ; var X = zone.style.width; //largeur zone var Y = zone.style.height; //hauteur zone var x = plongeur.style.left; //positionX du plongeur dans zone var y = plongeur.style.top ; //positionY du plongeur dans zone console.log("largeur zone :" + X + " " + typeof(X)); console.log("hauteur zone :" + Y + " " + typeof(Y)); console.log("positionX du plongeur " + x + " " + typeof(x)); console.log("positionY du plongeur " + y + " " + typeof(x)); X =parseInt(X); Y =parseInt(Y); // convertir X et Y en entiers x_maxi = X -100; y_maxi = Y-50 ; // l'image fait 100 par 50 var deltax = 3 ; var deltay = 2 ; // car la zone fait 600 par 400 donc un rapport 3/2 var boucle = setInterval(fdeplacement,50) ; document.querySelector('button').onclick = function() {clearInterval(boucle); } function fdeplacement() { // exécutué toutes les 50 millisecondes donc x = parseInt(x) ; y = parseInt(y) ; if(x > x_maxi || y > y_maxi) {deltax = -deltax ; deltay = -deltay ;} if(x < 0 || y < 0 ) {deltax =-deltax ; deltay =-deltay ; } x+=deltax ; y+=deltay ; x = x+'px' ; y = y+'px' ; plongeur.style.left = x ; plongeur.style.top = y ; } </script> ...

Commentaire du code

Comme dans la page précédente un gif animé (ici un plongeur) est positionnée en absolu dans une boîte DIV qui fait 600px par 400px.
Donc la zone d'animation ici n'est pas adaptative donc les valeurs de top & left doivent être exprimées en "px" !

Comme dans la page précédente on utilise les variables x et y mais aussi X,Y, x_maxi et y_maxi car ici le "sprite" ne doit pas sortir de la zone d'animation.
x_maxi et y_maxi représentent les valeurs maximales de left et top pour que le "plongeur" ne sorte pas du décor.
Le gif animé a une taille de 100 par 50. Pour que le plongeur ne sorte pas du décor il faut régler x_maxi à X - 100 et y_maxi à Y - 50.
Pour calculer x_maxi & y_maxi il faut au préalable convertir X & Y (dimensions en pixels de la zone) en entiers.

var boucle = setInterval(fdeplacement, 50) : signifie que la fonction fdeplacement est exécutée selon une fréquence de 50 millisecondes. La répétition est identifiée par la variable boucle.
clearInterval(boucle) : met fin à "boucle".

Mais en quoi consiste la fonction fdeplacement ?
Le plongeur doit se déplacer en diagonale dans les deux sens et sans sortir du décor.
Les variables x, y doivent donc alternativement diminuer puis augmenter.
Donc les variables deltax, deltay doivent alternativement être négatives puis positives.
deltax = -deltax et deltay = -deltay : grâce à ces instructions les variables deltay et deltay changent de signe.
deltax & deltay changent de signe lorsqu'il y a un "effet de bord". Dès que les bords droit ou bas sont atteints ces variables deviennent négatives. Dès que les bords gauche ou haut sont atteints ces variables redeviennent positives.


Testez cette animation !

Déplacer les "sprites" par le clavier

Si vous connaissez l'objet Event vous savez que l'une des propriétés de cet objet est keyCode (code ASCII de la touche appuyée).
Vous devez alors comprendre le code du jeu ci-dessous car il repose sur la programmation du clavier.

Il s'agit d'un jeu certes "bébête" mais l'intérêt est que sa programmation est simple , à votre niveau (lol) !
Ce jeu se joue à deux ! Un joueur déplace le requin avec les touches "gauche" "droite" "haut" "bas" du clavier pour tenter de croquer le plongeur.
L'autre joueur déplace le plongeur avec les touches U (up) D (down) L (left) et R (right) du clavier pour échapper aux dents du requin.

Le code de la page (extraits)

... <body> ... <div id = 'decor' style = "display : block ; width : 600px ; height : 400px ; position : relative ; background : url(../images/fond3.jpg) ; margin : auto ; background-size : cover;" > <img id ='requin' src ='../images/requin.gif' style = "position : absolute ; top : 10px; left : 20px ; " > <img id ='plongeur' src ='../images/plongeur3.gif' style = "position : absolute ; top : 350px; left : 500px ; " > </div> <script> var requin = document.querySelector('#requin') ; var plongeur = document.querySelector('#plongeur') ; var zone = document.querySelector('#decor'); X = zone.style.width ; // pour récupérer la largeur de la boîte X = parseInt(X) ; // conversion en entier Y = zone.style.height ; Y = parseInt(Y) ; x_maxi = X-100 ; y_maxi = Y-70; var xr = requin.style.left; var yr = requin.style.top; var xp = plongeur.style.left; var yp = plongeur.style.top; document.onkeydown = fclavier_lire; // fonction appelée à chaque fois qu'une touche du clavier est enfoncée function fclavier_lire(e) { // déplacement requin if (e.keyCode == 37) gauche_r(); if (e.keyCode == 39) droite_r(); if (e.keyCode == 38) haut_r(); if (e.keyCode == 40) bas_r(); // déplacement plongeur if (e.keyCode == 76) gauche_p(); if (e.keyCode == 82) droite_p(); if (e.keyCode == 85) haut_p(); if (e.keyCode == 68) bas_p(); } // fonctions pour déplacement du requin function gauche_r() { xr = parseInt(xr) ; xr = xr - 6 ; if( xr <= 0) xr = 0; xr = xr +'px' ; requin.style.left = xr ; } function droite_r() { xr = parseInt(xr) ; xr = xr + 6 ; if (xr >= x_maxi) xr = x_maxi ; xr = xr +'px' ; requin.style.left =xr ;} function haut_r() { yr = parseInt(yr) ; yr= yr - 6; if (yr <= 0) yr = 0 ; yr = yr +'px' ; requin.style.top = yr ; } function bas_r() { yr = parseInt(yr) ; yr= yr + 6; if (yr >= y_maxi) yr = y_maxi ;yr = yr +'px' ; requin.style.top = yr ; } // fonctions pour déplacement du plongeur function gauche_p() { xp = parseInt(xp) ; xp = xp - 10 ; if( xp <= 0) xp = 0; xp = xp +'px' ; plongeur.style.left = xp ; } function droite_p() { xp = parseInt(xp) ; xp = xp + 10 ; if (xp >= x_maxi) xp = x_maxi ; xp = xp +'px' ; plongeur.style.left =xp ;} function haut_p() { yp = parseInt(yp) ; yp= yp - 10; if (yp <= 0) yp = 0 ; yp = yp +'px' ; plongeur.style.top = yp ; } function bas_p() { yp = parseInt(yp) ; yp= yp + 10; if (yp >= y_maxi) yp = y_maxi ;yp = yp +'px' ; plongeur.style.top = yp ; } </script> ...

Commentaire du code

Le code CSS et le code HTMl ne présentent aucune difficulté. La zone d'animation fait 600px par 400. Donc elle n'est pas adaptative. Les top et left de chaque "sprite" doivent être exprimés en "px".
Un gif (le requin) est positionné en haut à gauche de la boîte DIV et un autre gif (le plongeur est positionné en bas à droite).

Par contre le JS présente une grande nouveauté : la programmation des touches du clavier.
document.onkeydown = fclavier_lire: si frappe d'une touche du clavier alors appel de la fonction fclavier_lire.
function fclavier_lire(e): dans cette instruction l'argument e représente l'évènement qui a entre autres comme propriété keyCode

if (e.keyCode == 37) gauche_r() : Chaque touche a un code ; la touche ← a le code 37. Donc si appui sur la touche ← appel de la fonction gauche_r

Ces fonctions ne présentent aucune difficulté si vous avez compris le code des pages "animation1.htm" et "animation2.htm".


Jouez !

Les autres technologies

Reprenons le thème du requin que l'on déplace dans un superbe décor corallien.

Sachez que la zone d'animation peut être une balise Canvas ou une balise SVG.
Gros avantage : plus besoin de positionner en absolu les "sprites" dans la zone.
Les zones de dessin Canvas et SVG ont un système de coordonnées classique avec deux axes.

Je n'en dis pas plus car il y a dans mon site un tuto sur l'animation avec SVG et un autre sur l'API Canvas. Solution avec Canvas Solution avec SVG & JS

Fin de ce chapitre !


Retour menu