requestAnimationFrame/cancelAnimationFrame——性能更好的js动画实现方式
2016-05-09 13:44
711 查看
用js来实现动画,我们一般是借助setTimeout或setInterval这两个函数,css3动画出来后,我们又可以使用css3来实现动画了,而且性能和流畅度也得到了很大的提升。但是css3动画还是有不少局限性,比如不是所有属性都能参与动画、动画缓动效果太少、无法完全控制动画过程等等。所以有的时候我们还是不得不使用setTimeout或setInterval的方式来实现动画,可是setTimeout和setInterval有着严重的性能问题,虽然某些现代浏览器对这两函个数进行了一些优化,但还是无法跟css3的动画性能相提并论。这个时候,就该requestAnimationFrame出马了。
requestAnimationFrame 是专门为实现高性能的帧动画而设计的一个API,目前已在多个浏览器得到了支持,包括IE10+,Firefox,Chrome,Safari,Opera等,在移动设备上,ios6以上版本以及IE mobile 10以上也支持requestAnimationFrame,唯一比较遗憾的是目前安卓上的原生浏览器并不支持requestAnimationFrame,不过对requestAnimationFrame的支持应该是大势所趋了,安卓版本的chrome
16+也是支持requestAnimationFrame的。
requestAnimationFrame 比起 setTimeout、setInterval的优势主要有两点:
1、requestAnimationFrame 会把每一帧中的所有DOM操作集中起来,在一次重绘或回流中就完成,并且重绘或回流的时间间隔紧紧跟随浏览器的刷新频率,一般来说,这个频率为每秒60帧。
2、在隐藏或不可见的元素中,requestAnimationFrame将不会进行重绘或回流,这当然就意味着更少的的cpu,gpu和内存使用量。
像setTimeout、setInterval一样,requestAnimationFrame是一个全局函数。调用requestAnimationFrame后,它会要求浏览器根据自己的频率进行一次重绘,它接收一个回调函数作为参数,在即将开始的浏览器重绘时,会调用这个函数,并会给这个函数传入调用回调函数时的时间作为参数。由于requestAnimationFrame的功效只是一次性的,所以若想达到动画效果,则必须连续不断的调用requestAnimationFrame,就像我们使用setTimeout来实现动画所做的那样。requestAnimationFrame函数会返回一个资源标识符,可以把它作为参数传入cancelAnimationFrame函数来取消requestAnimationFrame的回调。怎么样,是不是也跟setTimeout的clearTimeout很相似啊。
所以,可以这么说,requestAnimationFrame就是一个性能优化版、专为动画量身打造的setTimeout,不同的是requestAnimationFrame不是自己指定回调函数运行的时间,而是跟着浏览器内建的刷新频率来执行回调,这当然就能达到浏览器所能实现动画的最佳效果了。
目前,各个支持requestAnimationFrame的浏览器有些还是自己的私有实现,所以必须加前缀,对于不支持requestAnimationFrame的浏览器,我们只能使用setTimeout,因为两者的使用方式几近相同,所以这两者的兼容并不难。对于支持requestAnimationFrame的浏览器,我们使用requestAnimationFrame,而不支持的我们优雅降级使用传统的setTimeout。把它们封装一下,就能得到一个统一兼容各大浏览器的API了。
//简化版本
下面举个简单的例子来说明怎么运用requestAnimationFrame进行动画,下面的代码会将id为demo的div以动画的形式向右移动到300px
参考资料:
/article/5062192.html
http://www.paulirish.com/2011/requestanimationframe-for-smart-animating/
http://msdn.microsoft.com/zh-cn/library/ie/hh920765(v=vs.85).aspx
https://developer.mozilla.org/zh-CN/docs/Web/API/window.requestAnimationFrame
requestAnimationFrame 是专门为实现高性能的帧动画而设计的一个API,目前已在多个浏览器得到了支持,包括IE10+,Firefox,Chrome,Safari,Opera等,在移动设备上,ios6以上版本以及IE mobile 10以上也支持requestAnimationFrame,唯一比较遗憾的是目前安卓上的原生浏览器并不支持requestAnimationFrame,不过对requestAnimationFrame的支持应该是大势所趋了,安卓版本的chrome
16+也是支持requestAnimationFrame的。
requestAnimationFrame 比起 setTimeout、setInterval的优势主要有两点:
1、requestAnimationFrame 会把每一帧中的所有DOM操作集中起来,在一次重绘或回流中就完成,并且重绘或回流的时间间隔紧紧跟随浏览器的刷新频率,一般来说,这个频率为每秒60帧。
2、在隐藏或不可见的元素中,requestAnimationFrame将不会进行重绘或回流,这当然就意味着更少的的cpu,gpu和内存使用量。
像setTimeout、setInterval一样,requestAnimationFrame是一个全局函数。调用requestAnimationFrame后,它会要求浏览器根据自己的频率进行一次重绘,它接收一个回调函数作为参数,在即将开始的浏览器重绘时,会调用这个函数,并会给这个函数传入调用回调函数时的时间作为参数。由于requestAnimationFrame的功效只是一次性的,所以若想达到动画效果,则必须连续不断的调用requestAnimationFrame,就像我们使用setTimeout来实现动画所做的那样。requestAnimationFrame函数会返回一个资源标识符,可以把它作为参数传入cancelAnimationFrame函数来取消requestAnimationFrame的回调。怎么样,是不是也跟setTimeout的clearTimeout很相似啊。
所以,可以这么说,requestAnimationFrame就是一个性能优化版、专为动画量身打造的setTimeout,不同的是requestAnimationFrame不是自己指定回调函数运行的时间,而是跟着浏览器内建的刷新频率来执行回调,这当然就能达到浏览器所能实现动画的最佳效果了。
目前,各个支持requestAnimationFrame的浏览器有些还是自己的私有实现,所以必须加前缀,对于不支持requestAnimationFrame的浏览器,我们只能使用setTimeout,因为两者的使用方式几近相同,所以这两者的兼容并不难。对于支持requestAnimationFrame的浏览器,我们使用requestAnimationFrame,而不支持的我们优雅降级使用传统的setTimeout。把它们封装一下,就能得到一个统一兼容各大浏览器的API了。
(function() { var lastTime = 0; var vendors = ['webkit', 'moz', 'ms', 'o']; for( var x=0 ; x<vendors.length ; ++x){ if ( window.requestAnimationFrame && window.cancelAnimationFrame ) { break; } 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); }; } }());
//简化版本
window.requestAnimationFrame=window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.msRequestAnimationFrame || window.oRequestAnimationFrame || function( callback ){ //为了使setTimteout的尽可能的接近每秒60帧的效果 window.setTimeout(callback,1000/60); } window.cancelAnimationFrame=window.cancelAnimationFrame || Window.webkitCancelAnimationFrame || window.mozCancelAnimationFrame || window.msCancelAnimationFrame || window.oCancelAnimationFrame || function( id ){ //为了使setTimteout的尽可能的接近每秒60帧的效果 window.clearTimeout( id ); }
下面举个简单的例子来说明怎么运用requestAnimationFrame进行动画,下面的代码会将id为demo的div以动画的形式向右移动到300px
<div id="demo" style="position:absolute; width:100px; height:100px; background:#ccc; left:0; top:0;"></div> <script> var demo = document.getElementById('demo'); function rander(){ demo.style.left = parseInt(demo.style.left) + 1 + 'px'; //每一帧向右移动1px } requestAnimationFrame(function(){ rander(); //当超过300px后才停止 if(parseInt(demo.style.left)<=300){ requestAnimationFrame(arguments.callee); } }); </script>
参考资料:
/article/5062192.html
http://www.paulirish.com/2011/requestanimationframe-for-smart-animating/
http://msdn.microsoft.com/zh-cn/library/ie/hh920765(v=vs.85).aspx
https://developer.mozilla.org/zh-CN/docs/Web/API/window.requestAnimationFrame
相关文章推荐
- 【Arduino官方教程第一辑】示例程序 3-2 模拟信号输入
- gradle 项目依赖的包太多导致不能build的异常
- CoreThink主题开发(九)使用H-ui开发博客主题之用户个人主页
- jsp页面从session和request域中取数据小结
- Android 中的消息模型(Message,MessageQueue,handle,looper)
- Codeforces 670E - Correct Bracket Sequence Editor 链表
- 64-Unique Binary Search Trees
- Arcengine 开发,FeatureClass新增feature时“The Geometry has no z-value”或"The Geometry has null z-value"的解决方案
- MUI-页面初始化
- Ultra-QuickSort--POJ2299(归并排序求逆序数对)
- UIButton setBackgroundImage与setImage区别
- UITabBarController使用
- android 你所不知道的类SpannableStringBuilder的总结--实现图文混排,查看更多,下划线等等
- Moqui之时间转换
- words in view Moqui resource code
- 区分Integer.getInteger和Integer.valueOf、Integer.parseInt() 的使用方法
- TestSuite很多skipped,报错Exception org.openqa.selenium.SessionNotCreatedException
- 专访|腾讯、阿里、adidas的服务方UID WORKS
- sdutoj 3252 Lowest Unique Price
- Android UI 优化 使用<include/>和 <merge />标签