# JavaScript Canvas Animation

This animation makes my fans spin up after several seconds, and it seems to have a sub-par framerate. I am trying to understand why, and optimize its performance.

Codepen

The animation function (this is the main part of the code):

function animate() {
t++
ctx.clearRect(0, 0, c.width, c.height);

for (var i = 40; i < max; i+= 60) {
var radius = Math.floor(i+Math.sin(t/10)*10)
ctx.beginPath()
ctx.arc(center[0], center[1], radius, 0, 2 * Math.PI, false)
ctx.closePath()
ctx.stroke()
}

requestAnimationFrame(animate)
}


The for loop draws the minimum number of circles needed in order to fill the screen. Their radius pulses in and out with a sine function based on the 't' variable.

Am I doing something wrong?

• Welcome to Code Review! Do you suspect something is wrong or are you just looking for general improvements? – Mast Sep 9 '15 at 23:38
• @Mast Thanks! I guess I'm just assuming that it's inefficient because it makes my macbook's fans spin up after maybe 10 seconds, whereas I've seen fullscreen canvas animations/apps that take basically no noticeable toll on my computer. – Marcus Plimsoll Sep 9 '15 at 23:40

I guess I'm just assuming that it's inefficient because it makes my macbook's fans spin up after maybe 10 seconds

That's not really a good measure of "efficiency". The browser is trying to render 60 frames per second. That's a frame every ~16ms. Of course that's going to cause your processor to churn.

Math.floor(i+Math.sin(t/10)*10)


You can use <number> | 0 to trim off the decimal places of your numbers. In some JS engines and certain versions of JS engines, bitwise operations are faster than your regular math functions.

2 * Math.PI


There is a very small penalty when accessing object properties and becomes evident when you use it all over the place. Since Math.PI is a constant value, it wouldn't hurt if you assigned it to a variable for direct access. In fact, 2 * Math.PI is also constant. Why not put the result in a variable and spare the engine a multiplication operation as well.

function animate() {
...
requestAnimationFrame(animate)
}


The issue with depending on just the render loop is the time it takes between updates. requestAnimationFrame can run faster or slower depending on conditions. If your "tweening" is time-sensitive, you might want to update based on delta-time instead.

• Thank you for the insight. I did some research, and after recreating it in a webGL renderer (Pixi.js), it runs without breaking a sweat. I think it's just a limitation of the 2d canvas context… – Marcus Plimsoll Sep 10 '15 at 1:51
• @MarcusPlimsoll That's because webgl is hardware accelerated. – Joseph Sep 10 '15 at 2:16