Question

Ce que je voudrais faire est dessiner mes graphiques sur un tampon, puis être en mesure de copier tout comme sur la toile pour que je puisse faire de l'animation et éviter vacillante. Mais je ne pouvais pas trouver cette option. Quelqu'un sait comment je peux aller à ce sujet?

Était-ce utile?

La solution

Le lien suivant utile, en plus de montrer des exemples et des avantages de l'utilisation double buffering, montre plusieurs autres Conseils de performance pour l'utilisation de l'élément de toile html5. Il comprend des liens vers des tests jsPerf, dont les résultats des tests globaux dans les navigateurs dans une base de données Browserscope. Cela garantit que les conseils de performance sont vérifiées.

http://www.html5rocks.com/en/tutorials/canvas/performance/

Pour votre commodité, j'ai inclus un exemple minimal de double buffering efficace 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);

Autres conseils

Une méthode très simple est d'avoir deux éléments toile au même endroit de l'écran et définir la visibilité pour le tampon que vous devez montrer. Dessiner sur le caché et retourner lorsque vous avez terminé.

Une partie du 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 []' détient les deux toiles-objets. Alors, quand vous voulez commencer à vous tirer encore besoin pour obtenir le contexte:

var context = Buffers[DrawingBuffer].getContext('2d');

Je l'ai Browsers Poignèe tout cela en mémoire tampon pour vous de ne pas repeindre la toile jusqu'à ce que le code qui dessine votre cadre est terminé. Voir aussi la liste de diffusion WHATWG: http: //www.mail- archive.com/whatwg@lists.whatwg.org/msg19969.html

Vous pouvez toujours faire var canvas2 = document.createElement("canvas"); et non l'annexer au DOM du tout.

Il suffit de dire puisque vous les gars semblent tellement obsédés par display:none; il semble juste plus propre et me mimicks l'idée de façon double tampon avec plus de précision que d'avoir juste une toile invisible gauchement.

Plus de deux ans plus tard:

Il n'y a pas besoin de « manuellement » mettre en œuvre le double buffering. M. Geary a écrit à ce sujet dans son livre "HTML5 Canvas" .

Pour réduire efficacement l'utilisation de scintillement requestAnimationFrame() !

Josh a demandé (un certain temps) sur la façon dont le navigateur sait « quand la fin du processus de dessin » afin d'éviter le scintillement. J'aurais commenté directement à son poste, mais mon représentant est pas assez élevé. Aussi c'est juste mon avis. Je n'ai pas faits pour le soutenir, mais je me sens assez confiant à ce sujet et il peut être utile pour les autres à lire à l'avenir.

Je devine que le navigateur ne « sait » pas quand vous êtes dessin fait. Mais tout comme la plupart javascript, aussi longtemps que l'exécution de votre code sans perdre le contrôle du navigateur, le navigateur est essentiellement bloqué et ne / ne peut pas mettre à jour / répondre à son interface utilisateur. Je devine que si vous désactivez la toile et dessinez votre cadre entier sans renoncer au contrôle du navigateur, il ne sera pas réellement attirer votre toile jusqu'à ce que vous avez terminé.

Si vous configurez une situation où vos rendu couvre plusieurs appels setTimeout / setInterval / de requestAnimationFrame, où vous décochez la toile dans un appel et dessiner des éléments sur votre toile dans les prochains appels, en répétant le cycle (par exemple) tous les 5 appels, je serais prêt à parier que vous verriez le scintillement puisque la toile sera mis à jour après chaque appel.

Cela dit, je ne suis pas sûr que je me fierais que. Nous sommes déjà au point que le javascript est compilé en code machine natif avant l'exécution (au moins ce que le moteur V8 de Chrome fait de ce que je comprends). Je ne serais pas surpris si elle n'a pas été trop longtemps avant que les navigateurs ont commencé à courir leur javascript dans un thread séparé de l'interface utilisateur et la synchronisation de tout accès aux éléments d'interface permettant l'interface utilisateur de mise à jour / répondre lors de l'exécution de javascript qui n'a pas été interface utilisateur accède. Lorsque / si cela arrive (et je sais qu'il ya de nombreux obstacles qui doivent être surmontés, comme les gestionnaires d'événements pendant que vous le coup d'envoi êtes toujours en cours d'exécution autre code), nous verrons probablement le scintillement sur l'animation de toile qui ne sont pas à l'aide une sorte de double tampon.

part, j'aime l'idée de deux éléments de toile positionnés au-dessus de l'autre et alternant qui est représenté / dessiné sur chaque trame. Assez unintrusive et probablement assez facilement ajouté à une application existante avec quelques lignes de code.

Pour les non-croyants, voici un code vacillante. Notez que je compensation explicitement pour effacer le cercle précédent.

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);
<!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>
</body></html>

Il n'y a pas vacillante dans les navigateurs web! Ils utilisent déjà en mémoire tampon DBL pour leur rendu. moteur js fera tout votre rendu avant de le montrer. En outre, le contexte sauvegarder et de restaurer seulement empiler les données de la matrice de transformation et autres, pas le contenu de la toile elle-même. Donc, vous n'avez pas besoin ou si vous voulez en mémoire tampon DBL!

Au lieu de rouler vos propres, vous allez probablement obtenir le meilleur kilométrage en utilisant une bibliothèque existante pour créer de l'animation JavaScript propre et sans scintillement:

Voici un populaire: http://processingjs.org

vous avez besoin de 2 toile: (notez le z-index et css position: absolute)

<canvas id="layer1" width="760" height="600" style=" position:absolute; top:0;left:0; 
visibility: visible;  z-index: 0; solid #c3c3c3;">
Your browser does not support the canvas element.
</canvas>
<canvas id="layer2" width="760" height="600" style="position:absolute; top:0;left:0; 
visibility: visible;  z-index: 1; solid #c3c3c3;">
Your browser does not support the canvas element.
</canvas>

vous pouvez remarquer que la première toile est visible et la seconde, il est caché l'idée qu'il est de tirer parti de ce qui est caché après que nous cacherons le visible et faire la toile cachés visibles. quand il est caché « effacer toile cachée

<script type="text/javascript">
var buff=new Array(2);
buff[0]=document.getElementById("layer1");
buff[1]=document.getElementById("layer2");

ctx[0]=buff[0].getContext("2d");
ctx[1]=buff[1].getContext("2d");
var current=0;
// draw the canvas (ctx[ current ]);
buff[1- current ].style.visibility='hidden';
buff[ current ].style.visibility='visible';
ctx[1-current].clearRect(0,0,760,600);
current =1-current;

Opera 9.10 est très lent et montre le processus de dessin. Si vous voulez voir un navigateur pour ne pas utiliser le double buffering, essayez Opera 9.10 out.

Certaines personnes ont suggéré que les navigateurs sont en quelque sorte déterminer quand la fin du processus de dessin, mais pouvez-vous expliquer comment ce travail peut? Je ne l'ai pas remarqué de scintillement évident dans Firefox, Chrome ou IE9 même lorsque le dessin est lent, il semble que c'est ce qu'ils font, mais comment cela est accompli est un mystère pour moi. Comment le navigateur saura jamais qu'il est rafraîchissant l'écran, juste avant que d'autres instructions de dessin sont à exécuter? Pensez-vous qu'ils juste temps si un intervalle de plus de 5 ms ou alors passe sans exécuter une instruction zone de dessin, il suppose qu'il peut en toute sécurité des tampons de swap?

Dans la plupart des cas, vous n'avez pas besoin de le faire, les outils de votre navigateur pour vous. ! Mais pas toujours utile

Il vous reste à mettre en œuvre quand est très compliqué votre dessin. La plupart des taux de rafraîchissement de l'écran est d'environ 60 Hz, cela signifie que les mises à jour d'écran par 16ms. Le taux de mise à jour peut près de ce numéro du navigateur. Si votre besoin de forme 100ms à compléter, vous verrez une forme inachevée. Ainsi, vous pouvez mettre en œuvre le double buffering dans cette situation.

J'ai fait un test: Clear a rect, wait for some time, then fill with some color. Si je mets le temps de 10ms, je ne verrai pas vacillante. Mais si je mets à 20ms, le vacillement arrive.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top