画布在一段时间后开始滞后
Canvas starts to lag after some time
复制:将鼠标聚焦在画布上,然后将鼠标绕圈旋转约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);
这将中止当前的帧更新请求,并允许您在不累积调用的情况下启动新循环。
因此,您还必须初始化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>
相关文章:
- 如何添加类,同时开始在文本字段中输入文本
- 希望日期开始结束于while循环中的一个房间id的一个数组
- ng模型内的ng重复的ng重复开始
- 在HTML/JavaScript中,有没有一种方法可以在图像开始加载时知道图像的最终布局尺寸
- Yii2从点击链接开始加载模式
- Jquery幻灯片以一行左侧的图像开始,但我希望它从右端开始
- 从REST服务器和Coffeescapet前端开始
- nodejs createReadStream从第n行开始
- 帆布游戏的滞后运动
- 处理第三方库发送的ajax请求的开始和结束事件
- 从头开始创建XLS文件
- 在开始时隐藏FX.slide内容,而不是在单击后隐藏
- 拖动开始时更改可拖动元素的大小
- jQuery Datepicker从日期开始设置默认值
- 水平视差滚动从头开始-没有插件(jQuery)
- 从工作日结束到下一个工作日开始的完整日历JS包装时间
- 在ISO转换后,JavaScript时间滞后了一个小时
- 避免吊装造成的滞后
- Marquee从左中开始
- 画布在一段时间后开始滞后