2013-06-21 17 views
5

Czy jest jakiś punkt w renderowaniu obrazów na płótnie?Wstępne renderowanie Canvas?

Przykładem,

var img; // Img object 

var pre = document.createElement("canvas"); 
pre.width = img.width; 
pre.height = img.height; 
var precon = pre.getContext("2d"); 

precon.drawImage(img, 0, 0); 

var canvas = document.createElement("canvas"); 
var ctx = canvas.getContext("2d"); 

for(var i =0; i < 10000; ++i) { 
    ctx.drawImage(pre, Math.random() * canvas.width, Math.random() * canvas.height); 
} 

ja nie widzę sensu, jak jesteś ciągle dzwoni context.drawImage bez względu na to co robisz, chyba że api płótno jest szybsze rysowanie obrazu z obiektu płótnie zamiast obiektu obrazu ?

Odpowiedz

14

Po pierwsze, muszę powiedzieć, że twój przykład nie jest odpowiedni do podkreślenia potrzeby i korzyści wstępnego renderowania na płótnie.

Dam ci lepszy przykład, jeśli musisz narysować wiele razy coś, co wymaga ciężkich obliczeń na płótnie.

Powiedzmy masz ten draw funkcję:

function complexDraw(ctx){ 
    ctx.drawImage(img, width, height); 
    // heavy computation goes here 
    // some transforms maybe 
    ctx.ctx.setTransform(-1, 0, 0, 1, 200, 200); 
    ctx.fillStyle = "rgba(100, 100, 255, 0.5)"; 
    ctx.fillRect(50, 50, 100, 100); 
    //maybe draw another img/video/canvas 
    ctx.drawImage(anotherImg, width, height); 
    // ... 
} 
function draw(){ 
    complexDraw(ctx); 
} 

Teraz powiedzmy, że chcesz pokazać aktualny czas na płótnie też. Oznacza to, że mamy zamiar dodać to na dole naszej draw funkcję:

function drawTime(ctx){ 
    ctx.fillText(new Date().getTime(), 10, 50); 
} 

A teraz nasza funkcja draw wygląda następująco:

function draw(){ 
    complexDraw(ctx); 
    drawTime(ctx); 
} 

Ponieważ chcesz zawsze pokazują aktualny czas , trzeba wywołać funkcję draw każdy drugie:

setInterval(draw, 1000); 

To faktycznie oznacza, że ​​co drugi robisz jakiś skomplikowanych obliczeń tylko do aktualizacji głupi mały tekst.

Jeśli tylko istnieje możliwość podziału funkcji draw i obliczania tylko tych rzeczy, które wymagają obliczeń (tych, które się zmieniają) ... ale istnieje: przywitaj się na wstępie renderowania na płótnie!

Kluczową ideą jest narysowanie części, która się nie zmienia (i nie trzeba jej ponownie obliczać) na osobnym kanwie - nazwijmy ją: cacheCanvas - i po prostu skopiuj jej treść na płótno naszej aplikacji za każdym razem, gdy chcesz przerysować rzeczy:

// suppose we have a `clone` function 
var cacheCanvas = clone(canvas), 
    cacheCtx = cacheCanvas.getContext('2d'); 

// let's draw our complex stuff on the cacheCanvas 
complexDraw(cacheCtx); 

// modify our main `draw` function to copy the result of the `complexDraw` 
// function, not to call it 
function draw(){ 
    ctx.drawImage(cacheCanvas, width, height); 
    drawTime(); 
} 

A teraz jesteśmy w zasadzie przerysowywania cały płótno każda sekunda, ale nie jesteśmy ponowne obliczenie całą ciężką pracę w complexDraw.

Chcę tylko zwrócić uwagę, że większość z płótna na podstawie gry nie można uruchomić przy 60fps (przerysować 60 razy na sekundę) bez jakiejś wzrost wydajności z wstępnego renderowania lub inną technikę zwaną płótno odkłady (do którego warto również zajrzeć).

+0

Tak, zaimplementowałem układanie warstw i łatwiej jest tworzyć takie rzeczy jak przewijanie paralaksów itp., Dzięki temu, był to genialny wgląd! – user2251919

+0

Dzięki za odpowiedź! W tworzonej przeze mnie grze na płótnie oddaję kilkaset prostokątów na każdą klatkę, aby teksturować mój krajobraz. To nie było opóźnione w mojej platformie, ale pomogłoby mi to zrobić to szybciej na wolniejszych komputerach. –