Domanda

Quello che mi piacerebbe fare è disegnare la mia grafica su un buffer e quindi in grado di copiarlo come è sulla tela in modo da poter fare animazione ed evitare lo sfarfallio. Ma non riuscivo a trovare questa opzione. Qualcuno sa come posso andare su questo?

È stato utile?

Soluzione

Il seguente link utili, oltre a mostrare esempi e vantaggi di utilizzare il doppio buffer, spettacoli diversi altri suggerimenti di prestazioni per utilizzando l'elemento HTML5 canvas. Esso contiene link a test jsPerf, che i risultati dei test aggregati attraverso i browser in un database Browserscope. Questo assicura che le punte delle prestazioni sono verificate.

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

Per comodità, ho inserito un esempio minimo di efficacia doppio buffering, come descritto in questo articolo.

// 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);

Altri suggerimenti

Un metodo molto semplice è quella di avere due tela-elementi nella stessa posizione dello schermo e impostare la visibilità per il buffer che è necessario mostrare. Disegnare sulla nascosti e capovolgere quando si è fatto.

Alcuni codice:

CSS:

canvas { border: 2px solid #000; position:absolute; top:0;left:0; 
visibility: hidden; }

Flipping in JS:

Buffers[1-DrawingBuffer].style.visibility='hidden';
Buffers[DrawingBuffer].style.visibility='visible';

DrawingBuffer=1-DrawingBuffer;

In questo codice matrice 'buffer []' tiene entrambi tela-oggetti. Quindi, quando si desidera iniziare a disegnare è ancora necessario per ottenere il contesto:

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

I browser che ho provato tutto gestire questo buffer per voi da non ridipingere la tela fino a quando il codice che disegna la cornice è stata completata. Si veda anche la mailing list WHATWG: http: //www.mail- archive.com/whatwg@lists.whatwg.org/msg19969.html

Si può sempre fare var canvas2 = document.createElement("canvas"); e non aggiungerlo al DOM a tutti.

Basta dire dal momento che voi ragazzi sembrano così ossessionati con display:none; sembra proprio pulito a me e imita l'idea di modo doppio buffer in modo più accurato che avere una tela goffamente invisibile.

Più di due anni dopo:

Non v'è alcuna necessità di 'manuale' implementare il doppio buffer. Mr Geary ha scritto su questo nel suo libro "HTML5 Canvas" .

Per ridurre in modo efficace l'uso sfarfallio requestAnimationFrame() !

Josh chiesto (un po 'indietro) su come il browser sa "quando il processo di disegno finisce" in modo da evitare lo sfarfallio. Avrei commentato direttamente al suo posto, ma il mio rappresentante non è abbastanza alto. Anche questa è solo la mia opinione. Non ho fatti una copia di backup, ma mi sento abbastanza fiducioso su di esso e può essere utile per gli altri la lettura di questo in futuro.

sto cercando di indovinare il browser non "sa" quando sei disegno fatto. Ma proprio come la maggior parte javascript, a patto che le corse di codice senza cedere il controllo al browser, il browser è essenzialmente sotto chiave e non sarà / non può aggiornare / rispondere alla sua interfaccia utente. Sto indovinando che se si cancella la tela e disegnare l'intero telaio senza cedere il controllo al browser, non sarà in realtà attirare la vostra tela fino a quando il gioco è fatto.

Se si imposta una situazione in cui i tuoi campate di rendering più chiamate setTimeout / setInterval / requestAnimationFrame, in cui si cancella la tela in una sola chiamata e disegnare elementi della tela nei prossimi diverse chiamate, ripetendo il ciclo (per esempio) ogni 5 chiamate, sarei pronto a scommettere che ci si vede lo sfarfallio in quanto la tela sarebbe stato aggiornato dopo ogni chiamata.

Detto questo, io non sono sicuro che mi fiderei. Siamo già al punto che javascript è compilato fino a codice macchina nativo prima dell'esecuzione (almeno questo è quello che il motore V8 di Chrome fa da quanto ho capito). Non sarei sorpreso se non era troppo a lungo prima browser iniziato gestione dei loro JavaScript in un thread separato dall'interfaccia utente e la sincronizzazione alcun accesso a elementi dell'interfaccia utente che consentono la UI di aggiornamento / rispondere durante l'esecuzione JavaScript che non è stato accedendo UI. Quando / se ciò accade (e capisco ci sono molti ostacoli che sarebbero da superare, come ad esempio i gestori di eventi dando il via, mentre si sta ancora in esecuzione altro codice), probabilmente vedremo sfarfallio sull'animazione tela che non utilizzano una sorta di doppio buffering.

Personalmente, amo l'idea di due elementi di tela posizionati uno sopra l'altro ed alternata che viene mostrato / disegnato su ogni fotogramma. Abbastanza non invadente e probabilmente abbastanza facilmente aggiunto a un'applicazione esistente con poche righe di codice.

Per i non credenti, ecco qualche codice di sfarfallio. Nota che sto esplicitamente di compensazione per cancellare il cerchio precedente.

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>

Non c'è nessun sfarfallamento nei browser web! Essi utilizzano già il buffering doppia per la loro resa. motore js farà tutto il vostro il rendering prima di mostrarlo. Inoltre, il contesto salvare e ripristinare impilare solo i dati della matrice di trasformazione e simili, non il contenuto tela stessa. Quindi, non è necessario o si desidera buffer DBL!

Invece di posizionare il proprio, si sta probabilmente andando a ottenere il miglior chilometraggio utilizzando una libreria esistente per la creazione di animazioni JavaScript pulita e priva di sfarfallio:

Ecco una popolare: http://processingjs.org

avete bisogno di 2 tela: (avviso il css z-index e la posizione: assoluta)

<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>

Si può notare che la prima tela è visibile e la seconda è nascosto l'idea è di disegnare sul nascosto dopo che avremo nascondere il visibile e rendere le tele nascoste visibili. quando è nascosta 'cancellare tela nascosto

<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 è molto lento e mostra il processo di disegno. Se volete vedere un browser non usa il doppio buffer, provare Opera 9.10 fuori.

Qualcuno ha suggerito che i browser sono in qualche modo determinare quando le estremità processo di disegno, ma può spiegare come che il lavoro può? Non ho notato alcun guizzo evidente in Firefox, Chrome o IE9 anche quando il disegno è lento, quindi sembra che sia quello che stanno facendo, ma come che si compie è un mistero per me. Come sarebbe il browser mai sapere che è rinfrescante display appena prima di disegno più istruzioni sono da eseguire? Pensi che solo il tempo è così se un intervallo di più di 5 ms e così va da senza eseguire un'istruzione disegno tela, assume si può tranquillamente buffer di swap?

Nella maggior parte dei casi, non è necessario fare questo, gli strumenti del browser per voi. Ma non sempre utile!

Si devono ancora implementare questa, quando il disegno è molto complicato. La maggior parte della velocità di aggiornamento dello schermo è di circa 60 Hz, significa che gli aggiornamenti dello schermo al 16 ms. frequenza di aggiornamento del browser potrebbe vicinanze di questo numero. Se la vostra necessità forma 100ms per essere completato, vedrete una forma incompleta. Quindi è possibile implementare il doppio buffer in questa situazione.

ho fatto un test: Clear a rect, wait for some time, then fill with some color. Se ho impostato il tempo di 10 ms, non vedrò sfarfallio. Ma se ho impostato a 20 ms, il tremolio accade.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top