用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相关推荐

  1. JS 动画基础: 细说 requestAnimationFrame

    JS 动画基础: 细说 requestAnimationFrame 文章目录 JS 动画基础: 细说 requestAnimationFrame 简介 参考 完整示例代码 正文 `setInterva ...

  2. JS 动画:给网页下个雪吧

    JS 动画:给网页下个雪吧 文章目录 JS 动画:给网页下个雪吧 简介 参考 完整示例代码 正文 1. 一朵雪花 2. 很多雪花 3. 让雪花动起来 4. 快速划过的雪花 5. 雪花摇曳 6. 最终效 ...

  3. css动画和js动画_CSS与JS动画:哪个更快?

    css动画和js动画 How is it possible that JavaScript-based animation has secretly always been as fast - or ...

  4. JS动画的多种实现方式及原理

    本文主要介绍了JS动画的三种实现方式及其原理,分别为: 1.利用setInterval控制动画位移量 这里举例说明如何通过setInterval定时器来实现匀速动画和缓慢减速动画,以及为何缓慢减速动画 ...

  5. [css] 为什么说对opacity进行动画要比box-shadow进行动画性能更好呢?

    [css] 为什么说对opacity进行动画要比box-shadow进行动画性能更好呢? opacity的动画过程既不会影响布局,也不需要重绘 个人简介 我是歌谣,欢迎和大家一起交流前后端知识.放弃很 ...

  6. css动画和js动画比较!

    原文地址:http://css-tricks.com/myth-busting-css-animations-vs-javascript/ 译文地址:https://github.com/classi ...

  7. aos.js动画_AOS库使滚动动画变得很酷

    aos.js动画 As front-end developer, a popular request you might get from your clients is to implement s ...

  8. css动画 和 js动画_CSS大师的动画建议

    css动画 和 js动画 Just over a week ago we were lucky enough to have Tiffany Brown join us on the SitePoin ...

  9. Velocity.js介绍 --js 动画实现

    原址:点击打开链接 Velocity.js介绍 本文英文原文地址:http://davidwalsh.name/intro-javascript-animation 就像许多开发者确信的那样,在Web ...

最新文章

  1. 永远不要对 AI 说:“我不行!”
  2. AB1601烧程序时注意事项
  3. CentOS7下安装nginx1.99
  4. python循环输入若干学生信息保存到字典、并按学号排序,Python实现按学生年龄排序的实际问题详解...
  5. java动态加载jar文件并执行方法
  6. 创建世界级品牌的大师忠告
  7. 5行代码可实现5倍Scikit-Learn参数调整的更快速度
  8. leetcode915. 分割数组
  9. vb.net html标签,VB.Net - 获取元素html的字符串/值?
  10. matlab ascii 异或,GPS数据包的ASCII异或校验和计算方法(VC++)
  11. Spring:@Transactional 注解使用讲解
  12. linux多线程调度设置
  13. stvd能编辑c语言吗,STVD自动生成的stm8_interrupt_vector.c中几个疑问
  14. 常用网络拓扑在网络规划设计中
  15. 每个人都是雕刻自己的艺术家,生活是你的背景
  16. IP协议(IP协议报头、MTU、网段划分、NAT技术、路由的工作过程)
  17. 汉王速录笔linux驱动下载,汉王速录笔v586s驱动
  18. 全球与中国马铃薯面粉市场深度研究分析报告
  19. Linux中使用sendmail发送邮件,指定任意邮件发送人
  20. 我的开源项目从0到1024的过程

热门文章

  1. 博客作业02---线性表
  2. Maven中使用tomcat:run 出现错误 org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException...
  3. NIO和Reactor
  4. 安装phpredis扩展以及phpRedisAdmin工具
  5. 福州华威集团旗下华威客运票务网页界面设计
  6. ADO.NET与XML的结合
  7. 觉得UtraWebGrid老不稳定
  8. badboy 不支持html5,html5_iframe.htm
  9. To rename a docker image
  10. SylixOS普通定时器精度分析