Ce que j'aimerais faire, c'est dessiner mes graphiques sur un tampon, puis pouvoir le copier tel quel sur le canevas afin que je puisse faire de l'animation et éviter les scintillements. Mais je n'ai pas trouvé cette option. Quelqu'un sait comment je peux m'y prendre?
Réponses
Trop de publicités?Une méthode très simple consiste à avoir deux éléments de canevas au même emplacement d’écran et à définir la visibilité du tampon à afficher. Dessinez sur le caché et retournez lorsque vous avez terminé.
Un code:
CSS:
canvas { border: 2px solid #000; position:absolute; top:0;left:0;
visibility: hidden; }
Retournement dans JS:
Buffers[1-DrawingBuffer].style.visibility='hidden';
Buffers[DrawingBuffer].style.visibility='visible';
DrawingBuffer=1-DrawingBuffer;
Dans ce code, le tableau 'Buffers []' contient les deux objets de travail. Ainsi, lorsque vous souhaitez commencer à dessiner, vous devez toujours connaître le contexte:
Canvas= Buffers[DrawingBuffer].getContext('2d');
Le suivant lien utile, en plus de montrer des exemples et des avantages de l'utilisation de la double mise en tampon, montre plusieurs autres conseils de performances pour l'utilisation de l'élément html5 canvas. Il comprend des liens vers jsPerf tests, l'ensemble des résultats des tests sur tous les navigateurs dans un Browserscope base de données. Cela garantit que les conseils de performances sont vérifiées.
http://www.html5rocks.com/en/tutorials/canvas/performance/
Pour votre commodité, j'ai inclus un exemple minimal de efficace le double buffering comme décrit dans l'article.
// canvas element in DOM
var canvas1 = document.getElementById('canvas1');
var context1 = canvas1.getContext('2d');
// buffer canvas
var canvas2 = document.createElement('canvas');
canvas2.width = 150;
canvas2.height = 150;
var context2 = canvas2.getContext('2d');
// create something on the canvas
context2.beginPath();
context2.moveTo(10,10);
context2.lineTo(10,30);
context2.stroke();
//render the buffered canvas onto the original canvas element
context1.drawImage(canvas2, 0, 0);
Les navigateurs que j'ai testés gèrent tous cette mise en mémoire tampon pour vous en ne repeignant pas la toile tant que le code qui dessine votre cadre n'est pas terminé. Voir aussi la liste de diffusion du WHATWG: http://www.mail-archive.com/whatwg@lists.whatwg.org/msg19969.html
Pour les non-croyants, voici un code scintillant. Notez que je m'efforce explicitement d'effacer le cercle précédent.
http://coderextreme.net/basketball2.html ( http://jsfiddle.net/GzSWJ/ )
<!DOCTYPE html>
<html>
<head><title>Basketball</title></head>
<body>
<canvas id="myCanvas" width="400" height="400" style="border:1px solid #c3c3c3;">
Your browser does not support the canvas element.
</canvas>
<script>
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
function draw_ball(ball) {
ctx.clearRect(0, 0, 400, 400);
ctx.fillStyle = "#FF0000";
ctx.beginPath();
ctx.arc(ball.x, ball.y, 30, 0, Math.PI * 2, true);
ctx.closePath();
ctx.fill();
}
var deltat = 1;
var ball = {};
ball.y = 0;
ball.x = 200;
ball.vy = 0;
ball.vx = 10;
ball.ay = 9.8;
ball.ax = 0.1;
function compute_position() {
if (ball.y > 370 && ball.vy > 0) {
ball.vy = -ball.vy * 84 / 86;
}
if (ball.x < 30) {
ball.vx = -ball.vx;
ball.ax = -ball.ax;
} else if (ball.x > 370) {
ball.vx = -ball.vx;
ball.ax = -ball.ax;
}
ball.ax = ball.ax / 2;
ball.vx = ball.vx * 185 / 186;
ball.y = ball.y + ball.vy * deltat + ball.ay * deltat * deltat / 2
ball.x = ball.x + ball.vx * deltat + ball.ax * deltat * deltat / 2
ball.vy = ball.vy + ball.ay * deltat
ball.vx = ball.vx + ball.ax * deltat
draw_ball(ball);
}
setInterval(compute_position, 40);
</script></body></html>
Il n'y a pas de scintillement dans les navigateurs Web! Ils utilisent déjà dbl buffering pour leur rendu. Le moteur Js fera tout votre rendu avant de le montrer. En outre, la sauvegarde et la restauration du contexte ne concernent que les données de la matrice transformationnelle de la pile, et non le contenu de la zone de dessin elle-même. Donc, vous n’avez pas besoin ou ne voulez pas de tampons dbl!