Uknowho
Uknowho

Reputation: 397

External elements slowing down canvas

I am developing a game using several canvases (3) on top of one another. I am close to finishing the game and I haven't yet optimized the performance.

Regardless, my main concern is that the game has performed pretty well so far, but being close to finish I am building a simple web page around the canvas to give a frame to the game. I am talking just putting the title of the game and a few links here and there, but suddenly the game is now choppy and slow!!! If remove those elements everything is smooth again.

The culprits are:

Is it possible that this few static elements interfere with the rendering of the game?

Thank you.

Upvotes: 0

Views: 93

Answers (1)

user1693593
user1693593

Reputation:

Anything with shadows, rounded corners or expensive effects such as blur cost a lot to render.

Modern browsers try to optimize this in various way but there are special cases which they can't get around just like that (updated render engines using 3D hardware can help in the future).

Shadows are closely related to blurring and needs to be composited per frame due to the possibility that the background, shadow color, blur range etc. could change. Rounded corners forces the browser to create an alpha mask instead of doing just a rectangular clip. The browser may cache some of these operations, but they'll add up in the end.

Text Shadow

A workaround is to "cache" the shadowed text as an image. It can be a pre-made image from Photoshop or it could be made dynamically using a canvas element. Then display this instead of the text+shadow.

Example

var ctx = c.getContext("2d"),
    txt = "SHADOW HEADER";

// we need to do this twice as when we set width of canvas, state is cleared
ctx.font = "bold 28px sans-serif";

c.width = ctx.measureText(txt).width + 20; // add space for shadow
c.height = 50;                             // estimated

// and again...
ctx.font = "bold 28px sans-serif";
ctx.textBaseline = "top";
ctx.textAlign = "left";
ctx.shadowBlur = 9;
ctx.shadowOffsetX = 9;
ctx.shadowOffsetY = 9;
ctx.shadowColor = "rgba(0,0,0,0.8)";
ctx.fillStyle = "#aaa";

ctx.fillText(txt, 0, 0);
body {background:#7C3939}
<canvas id=c></canvas>

The canvas element can now be placed as needed. In addition you could convert the canvas to an image and use that without the extra overhead.

Rounded Corners

Rounded corners on an element is also expensive and there are no easy way around this - the corners need to be cut one way or another and question is which method is fastest.

  • Let browser do it using CSS
  • Overlay the element with the outer corners covered in the same color as background - clunky but can be fast as no clipping is needed. However, more data need to be composited.
  • Use a mask in canvas directly via globalCompositeOperation. The chances are this would be the slowest method. Performance tests must be made for this scenario to find out which one works best overall.
  • Make a compromise and remove rounded corners all together.

Links

Also these could be replaced by clickable images. It's a bit more tedious but also these could be made dynamically using a canvas allowing the text to change ad-hoc.

CSS

I would also recommend experimenting with position: fixed; for some of the elements. When fixed is used, some browsers renders that element separately (gives it its own bitmap). This may be more efficient in some cases.

But do make some performance tests to see what combination is the best for your scenario.

Upvotes: 1

Related Questions