码迷,mamicode.com
首页 > 其他好文 > 详细

requestAnimationFrame动画控制详解

时间:2015-01-20 07:48:52      阅读:274      评论:0      收藏:0      [点我收藏+]

标签:前端开发   优化   补丁   动画性能   

前端开发whqet,csdn,王海庆,whqet,前端开发专家

还在使用setInterval吗,你out了,requestAnimationFrame可以实现更为经济、更加准确的控制动画,今天来看看它的来龙去脉。

------------------------------------------------------------

--我参加了博客之星评选,如果你喜欢我的博客,求投票,您的支持是我的动力之源走起!

-----------------------------------------------------------------------------------------------------------------

以往

在web动画、app动画中,我们经常通过setInterval或setTimeout定时修改DOM、CSS实现动画,如下面代码所示。

var timer=setInterval(function(){
   //一些动画
},1000/60)
//清除动画
clearInterval(timer);

不过如此动画的方式极为耗费资源,经常是这样的结果,刚开始比较流畅,5分钟之后动画就卡住了,于是“大家”都看不下去了,开始想这种办法。

简介

2011年左右,Paul Irish的《requestAnimationFrame for Smart Animating》首先介绍了requestAnimationFrame的使用,然后经过大家的努力《Timing control for script-based animations》在2013年成为了w3c的候选标准。

requestAnimationFrame的方式的优势如下:

1.经过浏览器优化,动画更流畅

2.窗口没激活时,动画将停止,省计算资源

3.更省电,尤其是对移动终端

requestAnimationFrame的使用方式,简单调用代码如下。

function animate() {
  // Do whatever
  requestAnimationFrame(animate);
  // Do something animate
  
}
//go->
requestAnimationFrame(animate);

有的时候我们必须要加一些控制,requestAnimationFrame也可以像setInterval一样返回一个句柄,然后我们可以取消它。控制动画代码如下。

var globalID;
function animate() {
  // Do whatever
  globalID=requestAnimationFrame(animate);
  // Do something animate
  
}
//when ot start
	globalID=requestAnimationFrame(animate);
//when to stop
	cancelAnimationFrame(globalID);

好了,介绍完了吧。先别走,对于一个前端开发者,我们不能如此“单纯”,因为浏览器太任性,谁知道这些浏览器都是怎么“想的”,我们要看看浏览器兼容情况。来上CanIUse

技术分享

桌面端除了万恶的IE系列低版本9-,移动端除了Opera Mini和Android Browser4.3-其他都支持。总支持率83.38%,不加前缀支持率81.98%,支持率不错。作为一个富有极客精神的前端er,我们还得继续,拯救那些“手里没钱、手里有权却榆木疙瘩,还在使用低版本浏览器”的同胞,来个polyfill

补丁

Paul Irish的简化版的补丁,补丁和使用如下代码所示。

// 补丁
window.requestAnimationFrame = (function(){
  return  window.requestAnimationFrame       ||
          window.webkitRequestAnimationFrame ||
          window.mozRequestAnimationFrame    ||
          function( callback ){
            window.setTimeout(callback, 1000 / 60);
          };
})();


// 使用

(function animate(){
  requestAnimationFrame(animate);
  //动画
})();

这个补丁可以较好的兼容支持该特性的浏览器,但是对于不支持的呢?这里讲了怎么添加,如何停止呢?于是我们的补丁还得继续……

(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);  
        };  
}());

有后来,又有了新更新,大家到github查看详情,代码贴过来,大家研究。

// requestAnimationFrame polyfill by Erik M?ller.
// Fixes from Paul Irish, Tino Zijdel, Andrew Mao, Klemen Slavi?, Darius Bacon

// MIT license

if (!Date.now)
    Date.now = function() { return new Date().getTime(); };

(function() {
    ‘use strict‘;
    
    var vendors = [‘webkit‘, ‘moz‘];
    for (var i = 0; i < vendors.length && !window.requestAnimationFrame; ++i) {
        var vp = vendors[i];
        window.requestAnimationFrame = window[vp+‘RequestAnimationFrame‘];
        window.cancelAnimationFrame = (window[vp+‘CancelAnimationFrame‘]
                                   || window[vp+‘CancelRequestAnimationFrame‘]);
    }
    if (/iP(ad|hone|od).*OS 6/.test(window.navigator.userAgent) // iOS6 is buggy
        || !window.requestAnimationFrame || !window.cancelAnimationFrame) {
        var lastTime = 0;
        window.requestAnimationFrame = function(callback) {
            var now = Date.now();
            var nextTime = Math.max(lastTime + 16, now);
            return setTimeout(function() { callback(lastTime = nextTime); },
                              nextTime - now);
        };
        window.cancelAnimationFrame = clearTimeout;
    }
}());

当然,实战的时候我们把这些代码单独放到一个文件中,到这里下载

最后,我们来个粒子案例,体会体会

参考文献和深入阅读

1. Paul Irish, requestAnimationFrame for Smart Animating

2. MDN, Window.requestAnimationFrame()

3. Chris Coyier, Using requestAnimationFrame

4. Matt West, Efficient Animations with requestAnimationFrame

5. W3C CR, Timing control for script-based animations

6. Polyfill for requestAnimationFrame/cancelAnimationFrame

7. 张鑫旭, CSS3动画那么强,requestAnimationFrame还有毛线用?

8. 朱永盛, 理解WebKit和Chromium: 渲染主循环(main loop)和requestAnimationFrame

感谢您耐心读完,如果对您有帮助,请支持我

----------------------------------------------------------

前端开发whqet,关注web前端开发,分享相关资源,欢迎点赞,欢迎拍砖。

---------------------------------------------------------------------------------------------------------

requestAnimationFrame动画控制详解

标签:前端开发   优化   补丁   动画性能   

原文地址:http://blog.csdn.net/whqet/article/details/42911059

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!