HTML canvas updates too many times after resize

2020-04-14 03:59发布

I have a canvas in which I animate stuff. I listen to the window resize event, update the canvas size and start the recursive drawing again. But it seems like the old draw() calls continue and this causes the animation to go faster than intended. Here is the code:

HTML

<canvas id="myCanvas" width="1000" height="1000"></canvas>

CSS

* {
  margin: 0;
  padding: 0;
}

html,
body {
  width: 100%;
  height: 100%;
}

canvas {
  display: block;
}

JavaScript

var canvas = document.getElementById("myCanvas");
var context = canvas.getContext('2d');
var frameCount = 0;
var count = 0;

var rectDistance = 100;
var rectSize = 72;
var rectOffset = (rectDistance - rectSize) / 2;
var angleSpeed = 1;

var draw = function() {
  count++;

  var xCount = canvas.width / rectDistance;
  var yCount = canvas.height / rectDistance;

  context.fillStyle = "rgba(255,255,255,1)";
  context.fillRect(0, 0, canvas.width, canvas.height);

  for (var i = 0; i < xCount; i++) {
    for (var j = 0; j < yCount; j++) {

      context.save();

      var r = Math.round(i / xCount * 255);
      var g = Math.round(j / xCount * 255);

      xPos = i * rectDistance + rectOffset + Math.sin(j + frameCount / 20) * 10;
      yPos = j * rectDistance + rectOffset + Math.cos(i + frameCount / 20) * 10;

      context.translate(xPos + rectSize / 2, yPos + rectSize / 2);
      context.rotate(frameCount / 100 * angleSpeed * Math.sin(frameCount / 500) * 5);

      context.fillStyle = "rgba(" + r + "," + g + ",0,1)";
      context.fillRect(-rectSize / 2, -rectSize / 2, rectSize, rectSize);
      context.restore();
    }
  }

  frameCount = frameCount + 1;
  requestAnimationFrame(draw);
};

window.addEventListener('resize', function() {
  setTimeout(function() {
    resizeCanvas();
  }, 500);
}, false);

function resizeCanvas() {
  canvas.width = window.innerWidth;
  canvas.height = window.innerHeight;

  draw();
}

// count the calls of draw() per second -> it's increasing on window.resize
function drawCalls() {
  setTimeout(function() {
    console.log("draw() called " + count + " times");
    count = 0;
    drawCalls();
  }, 1000)
}
drawCalls();

// start the loop
resizeCanvas();

How I can prevent the old draw() calls continue their recursive execution on resize?

Here is a codepen with the same issue: http://codepen.io/Sebkasanzew/pen/GZGZVP

1条回答
爱情/是我丢掉的垃圾
2楼-- · 2020-04-14 04:18

You are forgetting to cancel the setTimeout() - I would suggest the following:

var timer;

window.addEventListener('resize', function() {
  cancelAnimationFrame(timer);                  // cancel previous request
  timer = requestAnimationFrame(function() {    // create a new request
    resizeCanvas();
  })
});
查看更多
登录 后发表回答