画布在一段时间后开始滞后

Canvas starts to lag after some time

本文关键字:开始 滞后 一段时间      更新时间:2023-09-26

复制:将鼠标聚焦在画布上,然后将鼠标绕圈旋转约15秒。一开始你会注意到事情是多么顺利。过了一段时间,它开始失去光滑度,变得非常滞后。

js函数的一部分来自以下答案

使Rect移动更加平滑

var canvas = document.getElementById('canvas');
var ctx = document.getElementById('canvas').getContext('2d');
var x;
var y;
var tx = tx || 0;
var ty = ty || 0;
var xDir;
var yDir;
function followMouse(e) {
  x = e.offsetX;
  y = e.offsetY;
  moveObject();
}
function moveObject() {
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  var scale =  0.2 * Math.max(canvas.width, canvas.height);
  xDir = 0;
  yDir = 0;
  xDir = (x - tx) / scale;
  yDir = (y - ty) / scale;
  tx = tx != x ? tx + xDir : tx;
  ty = ty != y ? ty + yDir : ty;
  ctx.fillRect(tx - 25, ty + 25, 50, 10);
  if (tx != x || ty != y) {
    window.requestAnimationFrame(moveObject);
  }
}
function resizeCanvas() {
  canvas.width = window.innerWidth;
  canvas.height = window.innerHeight;
};
canvas.addEventListener('mousemove', _.throttle(function(e) {
  followMouse(e);
}, 30));
window.addEventListener('resize', resizeCanvas, false);
resizeCanvas();
html,
body {
  margin: 0;
  height: 100%;
}
canvas {
  display: block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
<canvas id="canvas"></canvas>

对于每个mousemove,都会启动一个新的循环。这些循环会积累起来,最终会减慢速度。

要解决此问题,您可以通过执行以下操作来实现cancelAnimationFrame()

...
var timer;
function followMouse(e) {
  x = e.offsetX;
  y = e.offsetY;
  cancelAnimationFrame(timer);
  moveObject();
}

然后在主循环中存储定时器参考:

...
timer = requestAnimationFrame(moveObject);

这将中止当前的帧更新请求,并允许您在不累积调用的情况下启动新循环。

因此,您还必须初始化xy,因为在移动鼠标之前,它们不会被初始化(这当然不能保证)。

var x = 0;
var y = 0;

注意:这种校正的一个副作用是,现在每帧只计算一次移动。当累积时,每帧运动被计算多次。要进行补偿,请将比例调整到较低的值(如下所示)。

修改示例

var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
var x = 0;
var y = 0;
var tx = tx || 0;
var ty = ty || 0;
var xDir;
var yDir;
var timer;
function followMouse(e) {
  x = e.clientX;
  y = e.clientY;
  cancelAnimationFrame(timer);
  moveObject();
}
function moveObject() {
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  var scale = 0.02 * Math.max(canvas.width, canvas.height);
  xDir = 0;
  yDir = 0;
  xDir = (x - tx) / scale;
  yDir = (y - ty) / scale;
  tx = tx != x ? tx + xDir : tx;
  ty = ty != y ? ty + yDir : ty;
  ctx.fillRect(tx - 25, ty + 25, 50, 10);
  if (tx != x || ty != y) {
    timer = requestAnimationFrame(moveObject);
  }
}
function resizeCanvas() {
  canvas.width = window.innerWidth;
  canvas.height = window.innerHeight;
};
canvas.addEventListener('mousemove', _.throttle(function(e) {
  followMouse(e);
}, 30));
window.addEventListener('resize', resizeCanvas, false);
resizeCanvas();
html,
body {
  margin: 0;
  height: 100%;
}
canvas {
  display: block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
<canvas id="canvas"></canvas>