2013-06-21 10 views
5

Gibt es einen Vorwand, Bilder auf Leinwand zu rendern?Canvas vor dem Rendern?

Ein Beispiel,

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

Ich sehe den Punkt nicht, wie Sie noch context.drawImage nennend, egal was Sie tun, es sei denn, die Leinwand api schneller ein Bild aus einer Leinwand Objekt Zeichnung und nicht als Bildobjekt ?

Antwort

14

Zunächst muss ich sagen, dass Ihr Beispiel nicht geeignet ist, die Notwendigkeit und die Vorteile von Canvas-Vor-Rendering hervorzuheben.

Ich gebe Ihnen ein besseres Beispiel, wenn Sie mehrere Male etwas zeichnen müssen, das starke Berechnungen auf einer Leinwand erfordert.

Angenommen, Sie haben diese draw Funktion:

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

Lassen Sie uns jetzt sagen, Sie die aktuelle Zeit auf der Leinwand zeigen wollen. Das bedeutet, dass wir gehen diese unserer draw Funktion am unteren Rand hinzuzufügen:

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

Und jetzt Funktion unserer Verlosung sieht wie folgt aus:

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

Da Sie wollen immer die aktuelle Uhrzeit , müssen Sie die draw Funktion in jeder Sekunde nennen: nur

setInterval(draw, 1000); 

das bedeutet eigentlich, dass jede Sekunde tun Sie einige schwere Berechnung eine aktualisieren dummer kleiner Text.

Wenn es nur eine Möglichkeit geben könnte, die draw-Funktion zu spalten und nur die Dinge zu berechnen, die eine Berechnung benötigen (die ändern) ... aber es gibt: Hallo zu Canvas-Pre-Rendering!

Die Schlüsselidee besteht darin, den Teil, der sich nicht ändert (und nicht neu berechnet werden muss) auf einer separaten Zeichenfläche zu zeichnen - nennen wir ihn cacheCanvas - und kopieren ihn einfach in den Arbeitsbereich unserer App wollen Sachen neu zu zeichnen:

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

Und jetzt sind wir im Grunde die ganze Leinwand jede Sekunde neu gezeichnet, aber wir sind nicht Neuberechnen alle die schwere Arbeit in complexDraw.

Ich möchte nur, dass die meisten der Leinwand-basierte Spiele nicht bei 60fps laufen kann (neu zeichnen 60 mal pro Sekunde) ohne eine Leistungssteigerung zu tun mit Pre-Rendering oder eine andere Technik namens Leinwand Schichtung (was auch einen Blick wert ist).

+0

Ja, ich habe Layering implementiert und finde es viel einfacher, Dinge wie Parallax Scrolling usw. zu erstellen, danke dafür, es war ein brillanter Einblick! – user2251919

+0

Danke für die Antwort! In einem Leinwandspiel, das ich mache, rende ich jedes Bild ein paar hundert Rectures, um meine Landschaft zu texturieren. Es war nicht Laggy auf meinem Rigg, aber das würde mir helfen, es auf langsameren Computern schneller zu machen. –

Verwandte Themen