requestAnimationFram 的优势及使用场景
利用seTimeout实现的动画在某些低端机上会出现卡顿、抖动的现象。 这种现象的产生有两个原因:
setTimeout的执行时间并不是确定的。在Javascript中, setTimeout 任务被放进了异步队列中,只有当主线程上的任务执行完以后,才会去检查该队列里的任务是否需要开始执行,因此 setTimeout 的实际执行时间一般要比其设定的时间晚一些。
刷新频率受屏幕分辨率和屏幕尺寸的影响,因此不同设备的屏幕刷新频率可能会不同,而 setTimeout只能设置一个固定的时间间隔,这个时间不一定和屏幕的刷新时间相同。
不过实现动画还可以使用requestAnimationFrame
requestAnimationFrame的方式的优势如下:
1.经过浏览器优化,动画更流畅
2.窗口没激活时,动画将停止,省计算资源
3.更省电,尤其是对移动终端
requestAnimationFrame最大的优势是
由系统来决定回调函数的执行时机。具体一点讲,如果屏幕刷新率是60Hz,那么回调函数就每16.7ms被执行一次,如果刷新率是75Hz,那么这个时间间隔就变成了1000/75=13.3ms,换句话说就是,requestAnimationFrame的步伐跟着系统的刷新步伐走。它能保证回调函数在屏幕每一次的刷新间隔中只被执行一次,这样就不会引起丢帧现象,也不会导致动画出现卡顿的问题.
一个进度指示器demo:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>requestAnimationFram</title> </head> <body> <div id='contener' style="background:linear-gradient(45deg, red, blue, black, yellow); height: 20px; line-height: 20px; width: 0px; display: inline-block; vertical-align: middle;"></div> <div id='content' style="height: 20px; line-height: 20px; display: inline-block; vertical-align: middle; margin-left: 5px;"></div> <br> <br> <div> </div> <button id='begin'>开始</button> </body> <script> //在页面上绘制一个进度条,值 0% =》 100% const btn = document.getElementById('begin'); const contener = document.getElementById('contener'); const content = document.getElementById('content'); let start; btn.addEventListener('click', rAF) function rAF() { contener.style.width = 0; let current = Date.now(); start = current; requestAnimationFrame(progess) } function progess() { contener.style.width = contener.offsetWidth + 5 + 'px'; content.innerHTML = contener.offsetWidth / 5 + '%'; if(contener.offsetWidth < 500) { let current = Date.now(); console.log(current - start); start = current; width = contener.style.width; requestAnimationFrame(progess); } } </script> </html>
演示效果: