Un canevas est un contexte 2D mais en ombrant le canevas et les formes on donne l'illusion de la 3D.
Plutôt qu'utiliser setInterval() (pour appeler régulièremenent la fonction d'animation) j'utilise
une nouvelle méthode JavaScript : requestAnimationFrame().
Code HTML :
La balise Canvas étant un élément HTML, on peut lui appliquer un joli dégradé CSS.
Le script :
La balise canvas définit un repère de 600 par 300.
Le script est orienté objet.
Je crée un objet "balle" via la notation JSON.
Jusqu'à présent j'ai utilisé la méthode clearRect() pour effacer le contenu antérieur du canevas.
Cliquez dans le canevas pour suspendre l'animation.
La balise canvas (dans cette page web) définit un repère de 600 par 300.
Le script est aussi orienté objet.
L'objet boule est ombré via un filtre ; une seule instruction pour ombrer au lieu de 4 ...
Un script oriénté objet n'est pas forcément plus court qu'un script procédural.
Le document HTML ci-dessous contient une "toile" avec un objet : une fusée.
Observez que la fusée est de plus en plus petite ; elle s'éloigne de notre regard.
Le répère cartésien de la toile fait 2400 par 2400.
Partie définition de l'objet : je crée un objet nommé "fusee" via le constructeur Path2D() ; fonction argumentée avec
un chemin SVG (exprimé en relatif).
Partie "animation" : le chemin comprenant la position initiale de l'objet, je dois modifier le contexte pour déplacer l'objet.
Pour donner un effet 3D j'opte pour un changement d'échelle : ctx.transform(.999,0,0,.999,0,0). Ainsi la fusée
non seulement se déplace mais aussi diminue de taille.
Dans le cadre de jeux vidéos il faut déplacer des "sprites" souvent via le clavier.
L'élément canvas définit un repère de 400 par 400.
La programmation du clavier en JS ne pose pas de difficultés particulières.
Êtes-vous capable de compléter le code afin que la raquette ne sorte pas de la 'toile'?
Vous pouvez me contacter via Facebook pour questions & suggestions :
Page Facebook relative à mon site
Animations Canvas - recours à la POO
Dans ce chapitre je vais vous présenter des outils modernes pour réaliser le script d'animation :
Une bannière animée avec Canvas
Attention, elle ne s'applique pas à l'objet de type contexte mais à l'objet window.
et appelle une fonction 60 fois par seconde donc rend les animations très fluides.
Attention, il faut deux instructions window.requestAnimationFrame() : une en dehors de la fonction (premier appel)
et une autre dans la fonction (récursivité).
La méthode window.cancelAnimationFrame() permet de mettre fin à l'animation.
La 'toile'
Le code correspondant
function f1()
{
var canevas = document.querySelectorAll('canvas')[0];
var contexte = canevas.getContext('2d');
var X = canevas.width ;
var Y = canevas.height;
contexte.shadowColor = 'grey';
contexte.shadowOffsetX = 6 ;
contexte.shadowOffsetY = 6 ;
contexte.shadowBlur = 6 ;
contexte.textAlign ='left';
contexte.fillStyle = 'olive';
contexte.textBaseline = 'middle';
contexte.lineWidth = 3;
contexte.font = " bold italic 60px arial" ;
var x = X ;
window.requestAnimationFrame(deplacement);
function deplacement()
{
contexte.clearRect(0,0,X,Y);
x = x-2 ;
if(x <-750) x = X ;
contexte.fillText('Meilleurs voeux pour 2026',x,50);
window.requestAnimationFrame(deplacement);
} // fin déplacement
} // fin f1
f1(); // appel f1
Canvas et POO
Exemple 1 : balle avec effet de trainée
Le code de ce document HTML
Une règle de style en ligne définit une bordure et un ombrage.
Le script
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var X = canvas.width ;
var Y = canvas.height;
var stop ;
// définition objet balle via la notation JSON
var balle =
{
x: 80,
y: 100,
vx: 4,
vy: 2,
rayon: 20,
color: "red",
dessin: function ()
{
ctx.beginPath();
ctx.arc(this.x, this.y, this.rayon, 0, Math.PI * 2, true);
ctx.closePath();
ctx.fillStyle = this.color;
ctx.fill();
},
}; // fin définition objet balle
function deplacer()
{
ctx.fillStyle = "rgba(255,255,255,0.3)";
ctx.fillRect(0,0,X,Y);
balle.dessin();
balle.x += balle.vx;
balle.y += balle.vy;
// gestion des rebonds
if(balle.x > X-20 || balle.x <= 20) {balle.vx = -balle.vx}
if(balle.y >= Y-20 || balle.y <= 20) {balle.vy = -balle.vy}
stop = window.requestAnimationFrame(deplacer);
} // fin deplacer
canvas.onclick = function() {window.requestAnimationFrame(deplacer);}
document.onkeydown = function() {window.cancelAnimationFrame(stop);}
...
Pour en savoir davantage sur JavaScript et la notation JSON, suivez le lien :
la POO en JavaScript
En remplaçant par la méthode fillRect() et en utilisant un remplissage semi-transparent, on obtient un effet de traînée.
Les deux instructions pour créer cet effet :
ctx.fillStyle = "rgba(255,255,255,0.3)";
ctx.fillRect(0,0,X,Y);
Exemple 2 : déplacement automatique d'une boule de billard
Le code correspondant
Une règle de style en ligne définit un fond vert clair, un bordurage, un ombrage et des coins arrondis.
Le script
function f2()
{
var canevas = document.querySelector("#canevas");
var ctx = canevas.getContext("2d");
var X =canevas.width;
var Y =canevas.height;
var stop;
var boule =
{
x: X/2,
y: Y/2,
vx: 2,
vy: 1,
rayon: 10,
color: "red",
dessin: function ()
{
ctx.beginPath();
ctx.filter ='drop-shadow(3px 3px 3px gray)';
ctx.arc(this.x, this.y, this.rayon, 0, Math.PI * 2, true);
ctx.closePath();
ctx.fillStyle = this.color;
ctx.fill();
},
}; // fin définition objet boule
boule.dessin();
stop = window.requestAnimationFrame(deplacer);
function deplacer()
{
ctx.clearRect(0, 0, X, Y);
boule.dessin();
boule.x += boule.vx;
boule.y += boule.vy;
// la boule ne doit sortir du canevas
if(boule.x > X-20 || boule.x <= 20) {boule.vx = -boule.vx}
if(boule.y >= Y-20 || boule.y <= 20) {boule.vy = -boule.vy}
stop = window.requestAnimationFrame(deplacer);
} // fin deplacer
canevas.onclick = function() {window.cancelAnimationFrame(stop);}
} // fin fonction f2
f2() ; // appel f2
L'intérêt de la POO n'est pas là ; un programme en POO est plus facile à comprendre donc à maintenir
car il est structuré : on distingue bien la partie "définition de l'objet" et la partie "animation de cet objet.
Exemple 3 : emploi du constructeur path2D
Il est possible d'appeler le constructeur Path2D dans la méthode de dessin d'un objet.
Le rendu
Le code de ce document HTML
Le canevas a pour fond une belle image de nuit étoilée.
Le script
var canevas = document.querySelector('canvas');
var ctx = canevas.getContext('2d');
X = canevas.width ; Y = canevas.height;
var stop;
var fusee = {
color : "white",
dessin : function()
{
ctx.fillStyle =this.color;
ctx.fill(new Path2D('M 2000 2200 v-25 l25 -50 v-200 l25 -50 l25 50 v200 l25 50
v25 l-50 -50 l-50 50 z'));
ctx.filter ='drop-shadow(2px 2px 2px black)';
},
}; // fin définition objet fusee
fusee.dessin();
function animer()
{
ctx.clearRect(0,0,X,Y);
ctx.transform(.999,0,0,.999,0,0);
fusee.dessin();
stop = window.requestAnimationFrame(animer);
}
canevas.onclick = function() {window.requestAnimationFrame(animer);}
document.onkeydown = function() {window.cancelAnimationFrame(stop);}
L'objet "fusee" est ombré via un filtre.
La programmation du clavier
Dans l'exemple ci-dessous vous verrez que ce n'est pas très compliqué.
Le rendu dans un autre onglet
Le code de ce document HTML
Code HTML
Le script
...
var canvas = document.querySelector("canvas");
var ctx = canvas.getContext("2d");
var X = canvas.width;
var Y = canvas.height;
var stop;
// définition objet raquette
var raquette =
{
x: X/2,
y: Y/2,
vx: 15,
vy: 15,
w: 70,
h:10,
dessin: function ()
{
ctx.fillStyle = 'navy';
ctx.filter ='drop-shadow(5px 5px 5px gray)';
ctx.fillRect(this.x,this.y, this.w, this.h);
},
}; // fin définition objet raquette
canvas.onclick =function()
{
stop = setInterval(boucle_jeu,50);
function boucle_jeu()
{
ctx.clearRect(0,0,X,Y);
raquette.dessin();
document.onkeydown = function(e)
{
if (e.keyCode == 37) {raquette.x -=raquette.vx; } //gauche
if (e.keyCode == 39) {raquette.x += raquette.vx; } //droite
if (e.keyCode == 38) {raquette.y -= raquette.vy; } // haut
if (e.keyCode == 40) {raquette.y += raquette.vy; } // bas
}
} // fin boucle_jeu
}
Il faut utiliser l'évènement onkeydown de l'objet document.
et la propriété keycode appliquée à l'objet de type event.
À chaque touche du clavier est associé un code ; les touches directionnelles du clavier on un code compris entre 37 et 40.