Accueil

Traduction

Tutoriel Canvas - sommaire

Tutoriel Canvas - recherche

L'auteur : Patrick Darcheville

Vous pouvez me contacter via Facebook pour questions & suggestions : Page Facebook relative à mon site

Animations Canvas - recours à la POO

Un canevas est un contexte 2D mais en ombrant le canevas et les formes on donne l'illusion de la 3D.

Une bannière animée avec Canvas

Plutôt qu'utiliser setInterval() pour appeler régulièremenent la fonction d'animation, je vais introduire une nouvelle méthode window.requestAnimationFrame()
Cette nouvelle méthode appelle la 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é).
window.cancelAnimationFrame() permet de mettre fin à l'animation.

La 'toile'

Le code correspondant

Code HTML :

La balise Canvas étant un élément HTML, on peut lui appliquer un joli dégradé CSS.
Les dégradés CSS ont un gros avantage : la syntaxe est particulièrement succincte.
Hélas on ne peut appliquer un dégradé CSS qu'à un élément du DOM ; or les formes dessinées dans une toile ne sont pas repris par le DOM.

Le script :

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 2022',x,50); 
		window.requestAnimationFrame(deplacement);
	} // fin déplacement
} // fin f1
f1(); // appel f1

Canvas et POO

Le document HTML ci-dessous contient une "toile".

Le code du document

Le code HTML

Le script

Le script est orienté objet.

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);}
canvas.onmouseout = function() {window.cancelAnimationFrame(stop);}

Analyse du script

J'utilise la POO dans ce script. Je crée un objet "balle" via la notation JSON.
La POO en JavaScript

Jusqu'à présent j'ai utilisé la méthode clearRect() pour effacer le contenu antérieur du canevas.
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);

Animation : déplacement d'une boule sur un billard

Le canevas représente un billard

La boule se déplace sur le billard ; le billard et la boule sont ombrées pour donner un effet 3D.
Le rebond de la boule est parfaitement géré par le script.

L'animation se déclenche automatiquement.
Cliquez dans le billard pour mettre fin au déplacement de la boule rouge.

Le code correspondant

Le code HTML :

La balise CANVAS est un élément HTML, on peut donc lui appliquer la propriété CSS box-shadow.

Le script

Le script est orienté objet.

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.shadowColor = 'grey';
		ctx.shadowOffsetX = 3 ; 
		ctx.shadowOffsetY = 3 ; 
		ctx.shadowBlur = 3 ; 
		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 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;
		// gestion des rebonds
		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

Nous voulons que la boule soit ombrée ; aussi il faut intégrer dans la méthode qui dessine l'objet quatre instructions basées respectivement sur les méthodes shadowColor(), shadowOffsetX(), shadowOffsetY(), shadowblur().

Si vous trouvez que la boule ne se déplace pas assez vite il suffit de modifier les valeurs des propriétés vx,vy.

Un programme oriénté objet n'est pas forcément plus court que s'il avait été écrit en procédural.
L'intérêt de l'objet n'est pas là. Un script orienté objet est plus facile à comprendre donc à maintenir.
Si vous n'êtes pas satisfait du rendu de la boule de billard vous savez où intervenir : dans la méthode "dessin".
Par contre si vous voulez, par exemple un effet de trainée il faut modifier la fonction d'animation.

Intégrer le constructeur Path2D dans la méthode qui dessine un objet

Vous voulez créer un objet qui correspond à une forme très complexe ?
Utilisez N instructions lineTo() serait fastidieux ...
Il suffit d'utiliser dans la méthode de dessin de l'objet le constructeur Path2D !

Exemple

Le document HTML ci-dessous contient une "toile" avec un objet.

Le code de ce document HTML

Le répère cartésien de la toile fait 1200 par 1200.

Le script

var canevas = document.querySelector('canvas'); 
var ctx = canevas.getContext('2d');
X = canevas.width ;
Y = canevas.height;
var fusee = {
	color : "red",
	dessin : function() 
	{
		ctx.fillStyle =this.color;
		ctx.fill(new Path2D('M 50 1200 v-25 l25 -50 
	v-200 l25 -50 l25 50 v200 l25 50 v25 l-50 -50 l-50 50 z'));
			
	}, 
}; // fin définition objet fusee	
fusee.dessin();

function animer()
{
	ctx.clearRect(0,0,X,Y);
	ctx.translate(2,-2);
	fusee.dessin();
	stop = window.requestAnimationFrame(animer);
}

canevas.onclick = 
	function() {window.requestAnimationFrame(animer);}
canevas.onmouseout = 
	function() {window.cancelAnimationFrame(stop);}

Je crée un objet nommé "fusee".
Il s'agit d'une forme complexe aussi j'intègre dans la méthode qui le dessine le constructeur Path2D.
Remarquez l'instruction dans la méthode : ctx.fill(new Path2D('M 50 1200 v-25 l25 -50 ... ));
Ce chemin est noté en relatif.