zoukankan      html  css  js  c++  java
  • 动画优化之window.requestAnimationFrame()

    requestAnimationFrame解决了浏览器不知道javascript动画什么时候开始、不知道最佳循环间隔时间的问题。

    编写动画循环的关键,是要知道延迟时间多长合适。一方面,循环时间必须足够短,这样才能保证动画效果更平滑流畅;另一方面,循环还要足够长,这样才能保证浏览器有能力渲染产生的变化。大多数显示器的刷新频率是60Hz,相当于每秒钟重绘60次。大多数浏览器都会对重绘操作加以限制,不超过显示器的重绘频率,因为即使超过了这个频率,用户体验也不会有提升。

    因此最平滑动画的最佳循环间隔是1000ms/60,约等于17ms。以这个循环间隔重绘的动画是平滑的,因为这个速度最接近浏览器的最高限速。为了适应17ms的循环间隔,多重动画可能需要加以节制,以便不会完成得太快。

    虽然与使用多组setTimeout()相比,使用setInterval()的动画循环效率更高。但是无论setTimeout()还是setInterval()都不十分精确。为它们传入的第二个参数,实际上只是指定了把动画代码添加到浏览器UI线程队列以等待执行的时间。如果队列前面已经加入了其他任务,那动画代码就要等前面的任务执行完成后再执行。如果UI线程繁忙,比如忙于处理用户操作,那么即使把代码加入队列也不会立即执行。

    requestAnimationFrame的速度是由浏览器决定的,不同浏览器会自行决定最佳的帧效率。

    <!DOCTYPE html>
    <html>
    <head>
        <title>window.requestFrame</title>
    </head>
    <body>
        <div style="border: 1px ; 200px;height: 200px;background-color: pink;position: absolute;" id="dv">
    
        </div>
        <script type="text/javascript">
            var divPosition = 0;
            var div = document.getElementById('dv');
            window.requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame;
            div_width = parseInt(div.style.width);
            function step(timestamp) {
                divPosition+=10;
                div.style.left = divPosition + 'px';
                if(divPosition < window.screen.availWidth - div_width){
                    requestAnimationFrame(step);
                }
            }
            requestAnimationFrame(step);
        </script>
    </body>
    </html>
    

      以上是requestAnimationFrame的运行代码,但是有的浏览器不支持requestAnimationFrame,所以兼容写法如下:

    if(!window.requestAnimationFrame) {
     window.requestAnimationFrame = (window.webkitRequestAnimationFrame ||
     window.mozRequestAnimationFrame ||
     window.oRequestAnimationFrame ||
     window.msRequestAnimationFrame ||
     function(callback) {
      var self = this, start, finish;
      return window.setTimeout(function() {
       start = +new Date();
       callback(start);
       finish = +new Date();
       self.timeout = 1000/60 - (finish - start);
      }, self.timeout);
     });
    }

    这段代码先检查了window.requestAnimationFrame函数的定义是否存在。如果不存在,就遍历已知的各种浏览器实现并替代该函数。如果还是找不到一个与浏览器相关的实现,它最终会采用基于JavaScript定时器的动画以每秒60帧的间隔调用setTimeout函数。

    更加优雅的requestAnimationFrame兼容封装代码:

    (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 - (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);
      };
    }());
    用IE6的以后吃方便面都没有调料包!!!
  • 相关阅读:
    smarty display和fetch的区别 简单
    ERRORLEVEL is not %ERRORLEVEL%
    孟岩 快速掌握一个语言最常用的50%
    Delphi 的用户们,早点开始享受 MSBuild 吧!
    DLL的Export和Import
    WinFX Architecture for developers
    孟岩 技术路线的选择重要但不具有决定性
    科技部基础软件产品重大专项2009年课题(基础软件产品部分 转载)
    nmake vs MSBuild
    关于nmake, build , sources 文件 WDM驱动程序设计之编译安装篇
  • 原文地址:https://www.cnblogs.com/H5C3XXN/p/7358012.html
Copyright © 2011-2022 走看看