Schotsl
Schotsl

Reputation: 227

Javascript performance drop when drawing multiple object

I've created a canvas where I draw 100 cubes, each with a diffrent speed, position and size. It runs just as i'd expect at the frame rate I want.

But when I switch to a diffrent programe it takes a few seconds for my laptop to adjust, so I'm unable to use any program for a few seconds, I think this might be because of the script and when I take a look at task manager my GPU usage goes up to 40%

Here is the code:

  var c = document.getElementById("myCanvas");
  var ctx = c.getContext("2d");

  var w = Math.max(document.documentElement.clientWidth, window.innerWidth || 0);
  var h = Math.max(document.documentElement.clientHeight, window.innerHeight || 0);

  c.setAttribute('width', w);
  c.setAttribute('height', h);

  var Ypos = [];
  var Xpos = [];
  var cubeWidth = [];
  var Yspeed = [];
  for (var i = 0; i < 100; i ++) cubeWidth[i] = getRandomInt(7, 10);
  for (var i = 0; i < 100; i ++) Yspeed[i] = getRandomInt(30, 90) / 10;
  for (var i = 0; i < 100; i ++) Ypos[i] = getRandomInt(0, c.height);
  for (var i = 0; i < 100; i ++) Xpos[i] = getRandomInt(0, c.width);

  setInterval( function() {
  ctx.clearRect(0, 0, c.width, c.height);

  for (var i = 0; i < 100; i ++) {
    Ypos[i] += Yspeed[i];

    if (Ypos[i] + cubeWidth[i] / 2 > h) {
    Ypos[i] = -cubeWidth[i] / 2;
    Xpos[i] = getRandomInt(0, c.width);
    }

    var width = 10;
    var height = 10;

    ctx.beginPath();
    ctx.moveTo(-cubeWidth[i] / 2 + Xpos[i], -cubeWidth[i] / 2 + Ypos[i]);
    ctx.lineTo(cubeWidth[i] / 2 + Xpos[i], -cubeWidth[i] / 2 + Ypos[i]);
    ctx.lineTo(cubeWidth[i] / 2 + Xpos[i], cubeWidth[i] / 2 + Ypos[i]);
    ctx.lineTo(-cubeWidth[i] / 2 + Xpos[i], cubeWidth[i] / 2 + Ypos[i]);
    ctx.lineTo(-cubeWidth[i] / 2 + Xpos[i], -cubeWidth[i] / 2 + Ypos[i]);
    ctx.stroke();
    ctx.closePath();
  }
  }, 1000/60);

  function getRandomInt(min, max) {
  return Math.floor(Math.random() * (max - min + 1)) + min;
  }

what could I do to fix this problem?

Upvotes: 1

Views: 59

Answers (1)

Reinstate Monica Cellio
Reinstate Monica Cellio

Reputation: 26143

Get rid of the setInterval() as that's definitely going to cause a problem and require the browser keeps active, even when the OS is trying to do other things. Wrap the drawing in a function of its own and make that function call itself when it's done, but use requestAnimationFrame() so it only draws when the window is active...

function() draw {
    ctx.clearRect(0, 0, c.width, c.height);

    for (var i = 0; i < 100; i ++) {
        Ypos[i] += Yspeed[i];

        if (Ypos[i] + cubeWidth[i] / 2 > h) {
            Ypos[i] = -cubeWidth[i] / 2;
            Xpos[i] = getRandomInt(0, c.width);
        }

        var width = 10;
        var height = 10;

        ctx.beginPath();
        ctx.moveTo(-cubeWidth[i] / 2 + Xpos[i], -cubeWidth[i] / 2 + Ypos[i]);
        ctx.lineTo(cubeWidth[i] / 2 + Xpos[i], -cubeWidth[i] / 2 + Ypos[i]);
        ctx.lineTo(cubeWidth[i] / 2 + Xpos[i], cubeWidth[i] / 2 + Ypos[i]);
        ctx.lineTo(-cubeWidth[i] / 2 + Xpos[i], cubeWidth[i] / 2 + Ypos[i]);
        ctx.lineTo(-cubeWidth[i] / 2 + Xpos[i], -cubeWidth[i] / 2 + Ypos[i]);
        ctx.stroke();
        ctx.closePath();
    }

    setTimeout(function() {
        window.requestAnimationFrame(draw);
    }, 1000 / 60);
}

// start the animation
draw();

You can find out more about requestAnimationFrame() here...

https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame

Upvotes: 2

Related Questions