Optimisation d'une animation dans canvas de html5
Bonjour, ayant plutôt l'habitude de réaliser mes animations en actionscript, je cherchais à comparer les deux technologies d'un point de vue fluidité et facilité de conception.
Je me suis focalisé sur une animation simple de dessin avec translation et rotation. une roue en déplacement avec un repère qui tourne à l'intérieur.
ci-joint mes deux tentatives de réalisation en javascript/html5
une sans utilisation de translate() rotate() et l'autre avec...
ci-joint :
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84
|
<!DOCTYPE html>
<!--
To change this license header, choose License Headers in Project Properties.
To change this template file, choose Tools | Templates
and open the template in the editor.
-->
<html>
<head>
<title>Roue javascript</title>
<meta charset="UTF-8">
</head>
<body>
<canvas id="canvas" width="1024" height="600">
<p> votre navigateur ne supporte pas Canvas. Mettez-le à jour</p>
</canvas>
<script type="text/javascript">
var canvas = document.querySelector('#canvas');
var context = canvas.getContext('2d');
var theta = 0; //angle de rotation en radian
var oldtheta = 0;//angle de rotation correspondant à la frame précédente
var R = 100; //rayon de la roue
var retour = new Boolean(false);
var penw = 3;
var pi=Math.PI;
function draw()
{
context.save();
context.strokeStyle = "black";
context.lineWidth = penw;
context.clearRect(R * oldtheta-penw, 10-penw, 2 * R+2*penw, 2 * R+2*penw); //obturation (on efface l'image précédente à chaque fois en tenant compte du pen width)
//dessin du contour de la roue
context.beginPath();
context.arc(R * theta+R, R + 10, R, 0, 2*pi);
context.stroke();
//dessin des quatre rayons
for (var i = 0; i <= 3; i++)
{
context.beginPath();
context.moveTo(R * (1+theta), R + 10);
context.lineTo(R * (1+theta+ Math.cos(theta + i * pi/2)), 10 + R * (1 + Math.sin(theta + i * pi/2)));
context.stroke();
}
//dessin du sol
context.beginPath();
context.moveTo(0, 2 * R + 13);
context.lineTo(canvas.width, 2 * R + 10+penw);
context.stroke();
if ((R * theta > canvas.width - 2*R) || (theta < 0)) {
retour = !retour;
}
}
function render()
{
draw();
window.requestAnimationFrame(render);
oldtheta = theta;
if (retour) {
theta += Math.PI / 180;
} else {
theta -= Math.PI / 180;
}
}
render();
window.requestAnimFrame =
window.requestAnimationFrame || // La fonction standard
window.webkitRequestAnimationFrame || // Chrome et Safari.
window.mozRequestAnimationFrame || // Firefox.
window.ORequestAnimationFrame || // Opera.
window.msRequestAnimationFrame; // Internet Explorer.
</script>
</body>
</html> |
la seconde :
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
|
<!DOCTYPE html>
<html>
<head>
<title>roue en javascript</title>
<meta charset="UTF-8">
</head>
<body>
<canvas id="canvas" width="1024" height="600">
<p> votre navigateur ne supporte pas Canvas. Mettez-le à jour</p>
</canvas>
<script type="text/javascript">
var canvas = document.querySelector('#canvas');
var context = canvas.getContext('2d');
var theta = 0; //angle de rotation en radian
var R = 100; //rayon de la roue
var retour = new Boolean(false);
var penw = 3;
function draw()
{
context.save();
//obturation (on efface la frame précédente=> peu efficace ici-ça plombe l'animation)
context.clearRect(0, 0, canvas.width, canvas.height);
context.translate(R * theta + R, R + 10);//déplacement de l'origine du canvas au centre de la roue
context.rotate(theta);//rotation des axes du canvas
context.strokeStyle = "black";
context.lineWidth = penw;
//dessin du contour de la roue
context.beginPath();
context.arc(0, 0, R, 0, 2 * Math.PI);
context.stroke();
//dessin des quatre rayons
for (var i = 0; i <= 3; i++)
{
context.beginPath();
context.moveTo(0, 0);
context.lineTo(R * Math.cos(i * Math.PI / 2), R * Math.sin(i * Math.PI / 2));
context.stroke();
}
context.restore();//retour de l'origine du contexte graphique sur (0,0) en supprimant la rotation
//dessin du sol
context.beginPath();
context.moveTo(0, 2 * R + 10 + penw);
context.lineTo(canvas.width, 2 * R + 10 + penw);
context.stroke();
//gestion de l'aller et retour
if ((R * theta >= canvas.width - 2 * R) || (theta < 0)) {
retour = !retour;
}
}
function render()
{
draw();
window.requestAnimationFrame(render);
if (retour) {
theta += Math.PI / 180;
} else {
theta -= Math.PI / 180;
}
}
render();
window.requestAnimFrame =
window.requestAnimationFrame || // La fonction standard
window.webkitRequestAnimationFrame || // Chrome et Safari.
window.mozRequestAnimationFrame || // Firefox.
window.ORequestAnimationFrame || // Opera.
window.msRequestAnimationFrame; // Internet Explorer.
</script>
</body>
</html> |
Ma question est : quelle est la meilleure méthode à adopter... faut-il privilégier la seconde méthode (translate() rotate() du canvas) plutôt que la première ?
Sachant qu'il faudrait que j'obture uniquement sur le dessin de la précédente frame dont le canvas a subi une rotation...
Des idées d'optimisation puisque je débute presque dans ce langage et que je ne suis pas convaincu de l'intérêt de migrer vers html5/javascript hormis les plantages de flashplayer et la désaffection de flash par les distributeurs de pub.