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?
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.
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.
Prerendering is the process where a dynamic page is processed at build time generating static HTML.
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).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With