requestAnimationFrame

这里会说下requestAnimationFrame的由来,以及为什么会出现它。同时也会横向对比下定时器以及延时器

早期的动画

动画是一个持续的过程。早期的时候动画都是通过定时器来实现的。看如下代码

(function() {
 function updateAnimations() { 
 doAnimation1(); 
 doAnimation2(); 
 // 其他任务
 } 
 setInterval(updateAnimations, 100); 
})();
  • 一般的计算器显示器的屏幕刷新频率是60HZ,这就意味着是每秒要绘制60次。大多数浏览器都会显示绘制频率。
  • 为了实现动画效果过渡平滑最佳的重绘间隔大约17/毫秒。以这个速度重绘可以实现最佳的滑动效果。
  • 但是即使是这样依然无法保证能平滑过度。因为延时器/定时器的执行的时机不定。虽然可以设置执行时间。即使将延时任务添加到队列中也无法保证能立马执行。这取决于上一个任务或是同步任务执行的时间长度
  • 从js层面无法得知浏览器的绘制时机。所以函数requestAnimationFrame就出现了

函数requestAnimationFrame

1. 执行时机

  • 在每次浏览器重绘之前执行

2. 使用方法

  • 函数requestAnimationFrame只允许传递一个参数。而且参数必须是一个函数
  • 参数函数会被加入到队列。在每次浏览器绘制之前将队列中的函数进行执行
  • 每添加一次再下次绘制执行后,需要再次添加
function updateProgress() {
 var div = document.getElementById("status"); 
 div.style.width = (parseInt(div.style.width, 10) + 5) + "%"; 
 if (div.style.left != "100%") { 
 requestAnimationFrame(updateProgress); 
 } 
} 
requestAnimationFrame(updateProgress);

3. 如何取消

在全局中提供了函数cancelAnimationFrame. 可以通过函数进行取消。大致的原理跟延时器/ 定时器保持一致

  • 在函数requestAnimationFrame将函数加入队列后,会返回一个id(可以将id理解为队列的位置)。可以通过执行函数cancelAnimationFrame来进行取消
let requestID = window.requestAnimationFrame(() => {
 console.log('Repaint!'); 
}); 
window.cancelAnimationFrame(requestID);

通过函数requestAnimationFrame进行节流处理

let enabled = true;
function expensiveOperation() { 
 console.log('Invoked at', Date.now()); 
} 
window.addEventListener('scroll', () => { 
 if (enabled) { 
 enabled = false; 
 window.requestAnimationFrame(expensiveOperation); 
 window.setTimeout(() => enabled = true, 50); 
 } 
});
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。