javascript - 滚动事件上带有 clearAnimationFrame 的 requestAnimationFrame
问题描述
关于 JavaScript 已经有很多问题了,(我认为)我理解这个概念,但是在这种情况下requestAnimationFrame
,有和没有之间有什么性能差异吗?cancelAnimationFrame
// Setup a timer
var timeout;
// Listen for resize events
window.addEventListener('scroll', function () {
console.log( 'no debounce' );
// Cancel last animation, if there's one
if (timeout) {
window.cancelAnimationFrame(timeout);
}
// Setup the new requestAnimationFrame()
timeout = window.requestAnimationFrame(function () {
// Run our scroll functions
console.log( 'debounced' );
});
}, false);
没有cancelAnimationFrame
:
// Setup a timer
var timeout;
// Listen for resize events
window.addEventListener('scroll', function () {
console.log( 'no debounce' );
// Setup the new requestAnimationFrame()
window.requestAnimationFrame(function () {
// Run our scroll functions
console.log( 'debounced' );
});
}, false);
我在每个代码上得到相同的结果。
但我想知道如果我不取消动画帧会发生什么。请求的函数是否堆积在内存中的某个地方或其他地方?
解决方案
var isRafLogged = false;
function rafCb(now) {
if (isRafLogged) {
console.log('rAF callback executed at: ', now, 'ms');
}
requestAnimationFrame(rafCb);
}
function onWindowScroll() {
// when in scroll, log aforescheduled rAF() only when in scroll
isRafLogged = true;
const now = performance.now();
console.log('scroll callback executed at: ', now, 'ms');
// when out of scroll, stop logging the rAF
setTimeout(function() {
isRafLogged = false;
});
}
requestAnimationFrame(rafCb);
window.addEventListener('scroll', onWindowScroll);
html,
body {
height: 10000px;
}
p {
font-size: 200px;
writing-mode: vertical-lr;
}
<p>.....................................................................................................................................................................................................................................................................................................................................................................</p>
如果我们同时安排一个连续的单独requestAnimationFrame
循环,我们将清楚地scroll
看到每个VSync 事件最多发生一次回调。rAF
scroll
因此回到你的主要问题
在这种情况下,使用和不使用 cancelAnimationFrame 是否有任何性能差异?
通常不会,因为您的requestAnimationFrame()
调用阻止了下一个scroll
回调,并且执行的滚动回调不能多于请求的帧回调,因此存在 1 比 1 的相关性,因为它们都在每帧渲染的最大值处发生。
但我想知道如果我不取消动画帧会发生什么。请求的函数是否堆积在内存中的某个地方或其他地方?
所有请求的动画帧回调都堆叠在内部回调池中,在最近的 Vsync 事件之前被刷新。所以是的,从技术上讲,删除预定回调的唯一方法是cancelAnimationFrame()
,但同样与您的情况无关,因为您的回调与窗口回调requestAnimationFrame()
“同时”发生。scroll
希望这是有道理的。
推荐阅读
- bash - 整个句子的 Bash 脚本用作文件名
- javascript - 我想验证来自 javascript 对象的电子邮件地址
- php - php文件上传返回false
- java - 为什么在 for 循环后不打印计数?
- javascript - 这两个函数调用到底有什么区别?
- mysql - 有没有办法将数据从 Excel 工作表中的一列加载到现有的 mysql 表中?
- javascript - 通过另一个函数添加新属性而不修改现有对象结构
- xamarin - 如何将标签的 FontFamily 绑定到 C# 中的动态资源
- reactjs - 使用 shell adb 命令创建 adb 客户端失败
- html - 登录到通过 HTML 框架可见的 Jenkins