再次认识requestAnimationFrame以及其polyfill库raf

2019-05-082867次阅读javascript
  • 帧:在动画过程中,每一幅静止画面即为一“帧”;
  • 帧率:即每秒钟播放的静止画面的数量,单位是fps(Frame per second)或赫兹(Hz);
  • 帧时长:即每一幅静止画面的停留时间,单位一般是ms(毫秒);
  • 丢帧:在帧率固定的动画中,某一帧的时长远高于平均帧时长,导致其后续数帧被挤压而丢失的现象;

在显示器上看到的动画,每一帧变化都是系统绘制出来的(GPU或者CPU)。它的最高绘制频率受限于显示器的刷新频率(而非显卡,大多数是60Hz或者75Hz)。帧频越高,屏幕上图片闪烁感就越小,稳定性也就越高。人的眼睛不容易察觉75Hz以上刷新频率带来的闪烁感。

一般我们都是通过定时器(setTimeout和setlterval)间隔来改变元素样式实现动画效果时,就会出现上面所说的掉帧造成图片闪烁感有点高。所以强烈推荐使用requestAnimationFrame优化Web动画

 

requestAnimationFrame

window.requestAnimationFrame() 方法告诉浏览器希望执行动画并请求浏览器调用指定的函数在下一次重绘之前更新动画。它采用系统时间间隔,保持最佳绘制效率,不会因为间隔时间过短,造成过度绘制,增加开销;也不会因为间隔时间太长,使动画卡顿不流畅,让各种网页动画效果能够有一个统一的刷新机制,从而节省系统资源,提高系统性能,改善视觉效果

requestAnimationFrame使用一个回调函数作为参数,这个回调函数会在浏览器重绘之前调用,由于功效只是一次性的,所以想实现连续的动效,需要递归调用

var start = null;
var element = document.getElementById('SomeElementYouWantToAnimate');
element.style.position = 'absolute';

function step(timestamp) {
//console.log(timestamp);//34.438+++++
  if (!start) start = timestamp;
  var progress = timestamp - start;
  element.style.left = Math.min(progress / 10, 200) + 'px';
  if (progress < 2000) {
    window.requestAnimationFrame(step);
  }
}

window.requestAnimationFrame(step);

 

requestAnimationFrame的优势

  • requestAnimationFrame会把每一帧中的所有DOM操作集中起来,在一次重绘或回流中就完成,并且重绘或回流的时间间隔紧紧跟随浏览器的刷新频率。

  • 在隐藏或不可见的元素中,requestAnimationFrame将不会进行重绘或回流,这当然就意味着更少的CPU、GPU和内存使用量。

  • requestAnimationFrame是由浏览器专门为动画提供的API,在运行时浏览器会自动优化方法的调用,并且如果页面不是激活状态下的话,动画会自动暂停,有效节省了CPU开销。

 

requestAnimationFrame浏览器兼容:IE10+;

 

requestanimationframe polyfill

(function() {
    var lastTime = 0;
    var vendors = ['ms', 'moz', 'webkit', 'o'];
    for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
        window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame'];
        window.cancelAnimationFrame = window[vendors[x]+'CancelAnimationFrame'] 
                                   || window[vendors[x]+'CancelRequestAnimationFrame'];
    }
 
    if (!window.requestAnimationFrame)
        window.requestAnimationFrame = function(callback, element) {
            var currTime = new Date().getTime();
            var timeToCall = Math.max(0, 16.7 - (currTime - lastTime));
            var id = window.setTimeout(function() { callback(currTime + timeToCall); }, 
              timeToCall);
            lastTime = currTime + timeToCall;
            return id;
        };
 
    if (!window.cancelAnimationFrame)
        window.cancelAnimationFrame = function(id) {
            clearTimeout(id);
        };
}());

 

requestAnimationFrame polyfill库raf

raf用于node和浏览器中的requestAnimationFrame polyfill

安装

npm install --save raf

引入requestAnimationFrame polyfill方法一:

import 'raf/polyfill';

引入requestAnimationFrame polyfill方法二:

require('raf').polyfill()

这样你就可以很开心地在代码中直接使用window.requestAnimationFrame、window.cancelAnimationFrame方法。从而不用担心IE10以下浏览器兼容性问题了。更多关于raf的方法与介绍看这里

 

上一篇: HTML引入或include包含其他HTML文件  下一篇: Webpack4使用SplitChunksPlugin进行代码拆分  

再次认识requestAnimationFrame以及其polyfill库raf相关文章