spectralbat
spectralbat

Reputation: 407

Taking advantage of foreground and background canvases in HTML5

Right now I have one large canvas where everything is drawn. The canvas is created directly in the JS file:

 var canvas = document.createElement ("canvas");
 var ctx = canvas.getContext("2d");
 canvas.width = document.width;
 canvas.height = document.height;
 document.body.appendChild(canvas);

It resizes itself to the browser window.

I have a gradient background being drawn onto the one canvas along with all the other elements. The colors for the background are randomly generated at each game mode change (eg when the main menu is toggled to the game, then the level end screen, etc). Currently I'm drawing these onto the canvas like this:

var grad1 = ctx.createRadialGradient(canvas.width / 2, canvas.height / 2, 0, canvas.width / 2, canvas.height / 2, 500);
grad1.addColorStop(0, bgGradStop1);
grad1.addColorStop(1, bgGradStop2);

ctx.fillStyle = grad1;
ctx.fillRect(0, 0, canvas.width, canvas.height);

I read numerous times that having a separate canvas for the background is better for performance. Is there anything specific that I need to do to make this effective or can I simply create another canvas and draw the background using the same exact code, only modified to use the other canvas, like this:

var grad1 = ctxBg.createRadialGradient(canvasBg.width / 2, canvasBg.height / 2, 0, canvasBg.width / 2, canvasBg.height / 2, 500);
grad1.addColorStop(0, bgGradStop1);
grad1.addColorStop(1, bgGradStop2);

ctxBg.fillStyle = grad1;
ctxBg.fillRect(0, 0, canvasBg.width, canvasBg.height);

Or does getting any performance benefit involve some totally different method of using the second canvas?

Also, if it really is just a matter of doing the exact same thing but on a different canvas, would there be any benefit to also for example moving the HUD text to its own canvas while other entities are moving? Even separating various types of entities onto their own canvases? How far does the benefit of multiple canvases actually stretch?

Upvotes: 1

Views: 1770

Answers (1)

Simon Sarris
Simon Sarris

Reputation: 63812

Or does getting any performance benefit involve some totally different method of using the second canvas?

You've got the right idea of how to do it, though I don't think a second canvas is necessary in your case.

The important thing from a performance perspective is that you don't want to have to keep constructing and filling the gradient. If all you're doing in your draw loop is:

ctx.fillStyle = grad1;
ctx.fillRect(0, 0, canvas.width, canvas.height);

Then you should be pretty swell here. I don't think having a second canvas in the background will help you much after that. There might be a slight performance boost, but who wants to have to keep track of additional DOM elements if you don't have to?

It's a little hard to test the performance of having a second canvas behind your main one, but instead of having two large canvases in the DOM one similar alternative is to draw the gradient an in-memory canvas and always call ctx.drawImage(inMemCan, 0, 0); instead of setting the gradient and drawing it. Drawing images is known to be fast, and using two canvases this way is probably close to the speed you could expect from two on-page canvases (and hopefully it would be faster).

So we could test drawing the gradient from an in-memory canvas to your main canvas versus drawing the plain old gradient. Here's a simple test with a large canvas:

http://jsperf.com/gradient-vs-immemcan

They're pretty equal it seems. If this one thing is the only thing in your background I wouldn't worry about it. There are probably bigger performance fish for you to fry first.

I'd save the benefit of multiple canvases for when a relatively complicated background updates rarely but independently of the foreground. If your background was instead made with 30 gradients and some paths, then using a second canvas (or an in-memory canvas to cache an image) would give you a sizable boost.


It resizes itself to the browser window.

Just a reminder that the full screen API works pretty well in webkit and firefox if you want to look into it in the future.

Upvotes: 2

Related Questions