性能更好的js动画实现方式——requestAnimationFrame
用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了。
代码可以到这里来查看:https://gist.github.com/chaping/88813f56e75b0fd43f8c
var lastTime = 0; var prefixes = 'webkit moz ms o'.split(' '); //各浏览器前缀var requestAnimationFrame = window.requestAnimationFrame; var cancelAnimationFrame = window.cancelAnimationFrame;var prefix; //通过遍历各浏览器前缀,来得到requestAnimationFrame和cancelAnimationFrame在当前浏览器的实现形式 for( var i = 0; i < prefixes.length; i++ ) {if ( requestAnimationFrame && cancelAnimationFrame ) {break;}prefix = prefixes[i];requestAnimationFrame = requestAnimationFrame || window[ prefix + 'RequestAnimationFrame' ];cancelAnimationFrame = cancelAnimationFrame || window[ prefix + 'CancelAnimationFrame' ] || window[ prefix + 'CancelRequestAnimationFrame' ]; }//如果当前浏览器不支持requestAnimationFrame和cancelAnimationFrame,则会退到setTimeout if ( !requestAnimationFrame || !cancelAnimationFrame ) {requestAnimationFrame = function( callback, element ) {var currTime = new Date().getTime();//为了使setTimteout的尽可能的接近每秒60帧的效果var timeToCall = Math.max( 0, 16 - ( currTime - lastTime ) ); var id = window.setTimeout( function() {callback( currTime + timeToCall );}, timeToCall );lastTime = currTime + timeToCall;return id;};cancelAnimationFrame = function( id ) {window.clearTimeout( id );}; }//得到兼容各浏览器的API window.requestAnimationFrame = requestAnimationFrame; window.cancelAnimationFrame = cancelAnimationFrame;
这样子我们就能在所有浏览器上使用requestAnimationFrame和cancelAnimationFrame了。
下面举个简单的例子来说明怎么运用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>
参考资料:
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
性能更好的js动画实现方式——requestAnimationFrame相关推荐
- JS 动画基础: 细说 requestAnimationFrame
JS 动画基础: 细说 requestAnimationFrame 文章目录 JS 动画基础: 细说 requestAnimationFrame 简介 参考 完整示例代码 正文 `setInterva ...
- JS 动画:给网页下个雪吧
JS 动画:给网页下个雪吧 文章目录 JS 动画:给网页下个雪吧 简介 参考 完整示例代码 正文 1. 一朵雪花 2. 很多雪花 3. 让雪花动起来 4. 快速划过的雪花 5. 雪花摇曳 6. 最终效 ...
- css动画和js动画_CSS与JS动画:哪个更快?
css动画和js动画 How is it possible that JavaScript-based animation has secretly always been as fast - or ...
- JS动画的多种实现方式及原理
本文主要介绍了JS动画的三种实现方式及其原理,分别为: 1.利用setInterval控制动画位移量 这里举例说明如何通过setInterval定时器来实现匀速动画和缓慢减速动画,以及为何缓慢减速动画 ...
- [css] 为什么说对opacity进行动画要比box-shadow进行动画性能更好呢?
[css] 为什么说对opacity进行动画要比box-shadow进行动画性能更好呢? opacity的动画过程既不会影响布局,也不需要重绘 个人简介 我是歌谣,欢迎和大家一起交流前后端知识.放弃很 ...
- css动画和js动画比较!
原文地址:http://css-tricks.com/myth-busting-css-animations-vs-javascript/ 译文地址:https://github.com/classi ...
- aos.js动画_AOS库使滚动动画变得很酷
aos.js动画 As front-end developer, a popular request you might get from your clients is to implement s ...
- css动画 和 js动画_CSS大师的动画建议
css动画 和 js动画 Just over a week ago we were lucky enough to have Tiffany Brown join us on the SitePoin ...
- Velocity.js介绍 --js 动画实现
原址:点击打开链接 Velocity.js介绍 本文英文原文地址:http://davidwalsh.name/intro-javascript-animation 就像许多开发者确信的那样,在Web ...
最新文章
- 永远不要对 AI 说:“我不行!”
- AB1601烧程序时注意事项
- CentOS7下安装nginx1.99
- python循环输入若干学生信息保存到字典、并按学号排序,Python实现按学生年龄排序的实际问题详解...
- java动态加载jar文件并执行方法
- 创建世界级品牌的大师忠告
- 5行代码可实现5倍Scikit-Learn参数调整的更快速度
- leetcode915. 分割数组
- vb.net html标签,VB.Net - 获取元素html的字符串/值?
- matlab ascii 异或,GPS数据包的ASCII异或校验和计算方法(VC++)
- Spring:@Transactional 注解使用讲解
- linux多线程调度设置
- stvd能编辑c语言吗,STVD自动生成的stm8_interrupt_vector.c中几个疑问
- 常用网络拓扑在网络规划设计中
- 每个人都是雕刻自己的艺术家,生活是你的背景
- IP协议(IP协议报头、MTU、网段划分、NAT技术、路由的工作过程)
- 汉王速录笔linux驱动下载,汉王速录笔v586s驱动
- 全球与中国马铃薯面粉市场深度研究分析报告
- Linux中使用sendmail发送邮件,指定任意邮件发送人
- 我的开源项目从0到1024的过程
热门文章
- 博客作业02---线性表
- Maven中使用tomcat:run 出现错误 org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException...
- NIO和Reactor
- 安装phpredis扩展以及phpRedisAdmin工具
- 福州华威集团旗下华威客运票务网页界面设计
- ADO.NET与XML的结合
- 觉得UtraWebGrid老不稳定
- badboy 不支持html5,html5_iframe.htm
- To rename a docker image
- SylixOS普通定时器精度分析