Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Canvas pre rendering?

Is there any point in pre-rendering images on canvas?

An example,

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

I don't see the point as you are still calling context.drawImage no matter what you do, unless the canvas api is faster drawing an image from a canvas object rather than image object?

like image 782
user2251919 Avatar asked Jun 21 '13 12:06

user2251919


People also ask

Should I pre render?

Pre-rendering can result in better performance and SEO. Each generated HTML is associated with minimal JavaScript code necessary for that page. When a page is loaded by the browser, its JavaScript code runs and makes the page fully interactive.

Is Canvas more performant than Dom?

In sum, the overhead of DOM rendering is more poignant when juggling hundreds if not thousands of objects; in this scenario, canvas is the clear winner. However, both the canvas and SVG are invariant to object sizes. Given the final tally, the canvas offers a clear win in performance.

What is static pre rendering?

Prerendering is the process where a dynamic page is processed at build time generating static HTML.


1 Answers

Firstly, I must say that your example is not suitable to highlight the need and benefits of canvas pre-rendering.

I'll give you a better example were you need to draw multiple times something that requires heavy computation on a canvas.

Let's say you have this draw function :

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

Now let's say you want to show the current time on the canvas too. That means that we're going to add this at the bottom of our draw function :

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

And now our draw function looks like this :

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

Since you want to always show the current time, you need to call the draw function every second :

setInterval(draw, 1000);

This actually means that every second you are doing some heavy computation just to update a silly little text.

If only there could be a way to split the draw function and compute only the things that need computing (the ones that change)... but there is: say hello to canvas pre-rendering!

The key idea is to draw the part that doesn't change (and doesn't need to be re-computed) on a separate canvas - let's call it cacheCanvas - and just copy it's content on our app's canvas whenever we want to redraw stuff :

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

And now we're basically redrawing the whole canvas each second, but we're not re-computing all the heavy work in complexDraw.

I just want to note that most of the canvas based games can't run at 60fps (redraw 60 times per second) without doing some performance boost with pre rendering or another technique called canvas layering (which is also worth looking into).

like image 104
gion_13 Avatar answered Nov 15 '22 19:11

gion_13