为了账号安全,请及时绑定邮箱和手机立即绑定

requestAnimationFrame最佳实践

标签:
Html5 JavaScript

requestAnimationFrame ,这个方法应该都不陌生,字面含义是请求动画帧。从API命名来看,和动画有着密切的关系。其用法跟setTimeout差不多,与setTimeout相比,最大的优势是 由浏览器来决定函数的执行时机 。形象一点的解释就是:告诉浏览器说 “我这里有一个函数要执行,你有空了帮忙执行一下”,然后浏览器相对比较空闲的时候就给执行了。

用法一:动画

raf api本身的设计就是用来解决js动画的性能问题。那么,为什么raf做动画性能会更好呢?主要原因在于 raf更加智能,它并非加快执行速度,而是适当时候降帧,防止并解决丢帧问题 。当它发现无法维持60fps的频率时,它会把频率降低到30fps来保持帧数的稳定。也就是说如果上一次raf的回调执行时间过长,那么触发下一次raf回调的时间就会缩短,反之亦然,这也是为什么说由浏览器来决定执行时机性能会更好。

(function animloop(){
  window.requestAnimFrame(animloop);
  render();})();

DEMO:

See the Pen bErOLz by hugo ( @baofen14787 ) on CodePen .

用法二: 函数节流

在高频率事件中,为了防止16ms内发生多次函数执行,使用raf可保证16ms内只触发一次,这既能保证流畅性也能更好的节省函数执行的开销。 16ms内函数执行多次没有意义,因为显示器16ms刷新一次,多次执行并不会在界面上有任何显示。

举个例子:

var $box = $('#J_num2'),
      $point = $box.find('i');$box.on('mousemove',function(e){
  requestAnimationFrame(function(){
      $point.css({
          top : e.pageY,
          left : e.pageX      })
  })})

用法三:CPU节能

raf的另一个特性是:如果页面不是激活状态下的话,函数会自动暂停,有效节省了CPU开销。在移动端,如果页面中有自动播放的轮播图、倒计时或使用 setTimeout/setInterval 来执行任务的定时器。那么 当app进到后台或是锁屏后,webviewcorethread仍然持续占用CPU,导致耗电 。而使用raf可以很简单的解决此类问题。

PS:复杂情况下,可配合 window.onblur & window.focus 、 document.onvisibilitychange 、 document.onpause & document.onresume 等相关的方法进行实现,但这篇文章里不做深入探讨。

(function(){
        var timer;
        var $txt = $('#J_num2'),
                num = 0;
        function play(){
            timer = setTimeout(function(){
                  //使用raf实现非激活状态下不运行
                requestAnimationFrame(function(){
                    stop();
                    next();
                });
            },1000)
        }

        function stop(){
            clearTimeout(timer)
        }

        function next(){
            $txt.text(num++);
            play();
        }
        play();
    })();

DEMO:

See the Pen OMxodB by hugo ( @baofen14787 ) on CodePen .

用法四:分帧初始化

都知道,raf的执行时间约为16.7ms,即为一帧。那么可以使用raf将页面初始化的函数进行打散到每一帧里,这样 可以在初始化时降低CPU及内存开销 

很多页面,初始化加载时,CPU都会有很明显的波动,就是因为大量的操作都集中到了一点上。

举个例子:

页面中有4个模块,A、B、C、D,在页面加载时进行实例化,一般的写法类似于:

$(function(){
    new A();
    new B();
    new C();
    new D();})

而使用raf可将每个模块分别初始化,即 每个模块都有16ms的初始化时间

    $(function(){
        var lazyLoadList = [A,B,C,D];
        $.each(lazyloadList, function(index, module){
        window.requestAnimationFrame(function(){new module()});
        }); 
        
    })

用法五:异步化

raf实际是一种异步化的操作,曾经 setTimeout(function(){},0) 一度成为解决了很多前端疑难杂症的法宝。而现在,可以用raf来代替。

原文链接:http://outofmemory.cn/html/javascript-animation-practice

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消