复制:将鼠标放在画布上,然后将鼠标旋转约15秒钟。起初你会注意到事情的顺利进行。一段时间后,它开始失去光滑度,变得非常迟钝。
部分js功能来自以下答案
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>
&#13;
答案 0 :(得分:1)
每个mousemove
启动一个新循环就会发生这种情况。这些循环会累积并最终减慢速度。
要解决此问题,您可以执行以下操作cancelAnimationFrame()
:
...
var timer;
function followMouse(e) {
x = e.offsetX;
y = e.offsetY;
cancelAnimationFrame(timer);
moveObject();
}
然后在主循环中存储定时器引用:
...
timer = requestAnimationFrame(moveObject);
这将中止当前的帧更新请求,并允许您在不累积调用的情况下启动新循环。
出于这个原因,你还必须初始化x
和y
,因为它们没有被初始化,否则直到移动鼠标(这当然不能保证)。
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>