性能更好的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
本文转载,原文地址:http://www.cnblogs.com/2050/p/3871517.html 用js来实现动画,我们一般是借助setTimeout或setInterval这两个函数,css ...
- 性能更好的js动画实现方式---requestAnimationFrame
用js来实现动画,我们一般是借助setTimeout或setInterval这两个函数,css3动画出来后,我们又可以使用css3来实现动画了,而且性能和流畅度也得到了很大的提升.但是css3动画还是 ...
- requestAnimationFrame/cancelAnimationFrame——性能更好的js动画实现方式
用js来实现动画,我们一般是借助setTimeout或setInterval这两个函数,css3动画出来后,我们又可以使用css3来实现动画了,而且性能和流畅度也得到了很大的提升.但是css3动画还是 ...
- js动画最佳实现——requestAnimationFrame
我们经常用setInterval来实现动画,其实这种做法不是太好,因为不同浏览器的刷新频率也不一样(一般认为设置16为最佳,按每秒60帧算,1000/60≍16.67) var dis = 0,tim ...
- JavaScript是如何工作的: CSS 和 JS 动画底层原理及如何优化它们的性能
摘要: 理解浏览器渲染. 原文:JavaScript是如何工作的: CSS 和 JS 动画底层原理及如何优化它们的性能 作者:前端小智 Fundebug经授权转载,版权归原作者所有. 这是专门探索 J ...
- CSS VS JS动画,哪个更快[译]
英文原文:https://davidwalsh.name/css-js-animation 原作者Julian Shapiro是Velocity.js的作者,Velocity.js是一个高效易用的js ...
- 关于JS动画和CSS3动画的性能差异
本文章为综合其它资料所得. 根据Google Developer,Chromium项目里,渲染线程分为main thread和compositor thread. 如果CSS动画只是改变transfo ...
- How Javascript works (Javascript工作原理) (十三) CSS 和 JS 动画底层原理及如何优化其性能
个人总结:读完这篇文章需要20分钟. 这是 JavaScript 工作原理的第十三章. 概述 正如你所知,动画在创建令人叹服的网络应用中扮演着一个关键角色.由于用户越来越注重用户体验,商户开始意识到完 ...
- JavaScript 工作原理之十三-CSS 和 JS 动画底层原理及如何优化其性能
原文请查阅这里,本文采用知识共享署名 4.0 国际许可协议共享,BY Troland. 本系列持续更新中,Github 地址请查阅这里. 这是 JavaScript 工作原理的第十三章. 概述 正如你 ...
随机推荐
- OpenCascade Ray Tracing Rendering
OpenCascade Ray Tracing Rendering eryar@163.com 摘要Abstract:OpenCascade6.7.0中引入了光线跟踪算法的实现.使用光线跟踪算法可实现 ...
- .NET面试题解析(05)-常量、字段、属性、特性与委托
系列文章目录地址: .NET面试题解析(00)-开篇来谈谈面试 & 系列文章索引 弱小和无知不是生存的障碍,傲慢才是!——<三体> 常见面试题目: 1. const和reado ...
- JQuery 实现页面无刷新
对于JQuery实现页面无刷新的效果,即:应用这个JQuery这个组件,可以实现在页面上加载数据库中的数据信息,但是并没有给用户页面刷新的感觉,这样既可以有效的进行数据交互,也可以不妨碍用户的其他操作 ...
- Windows Azure Cloud Service (41) 修改云服务IIS托管管道模式为4.0经典模式
<Windows Azure Platform 系列文章目录> 这是笔者在之前的项目中遇到的问题,做一下总结,给网友做参考. 在一般情况下,Visual Studio开发的Cloud Se ...
- sublime Text3使用笔记
转载:http://blog.csdn.net/u012771929/article/details/30030249 目录: 1.setting 安装插件,package control ,Emme ...
- 使用git提交中删除idea
https://segmentfault.com/q/1010000000720031 http://www.tuicool.com/articles/a6Nf63F 先有项目,然后分享至github ...
- oracle表数据类型number对应java中BIgDecimal转int
oracle中id为number类型,在java获取id时用getBigDecimal 相匹配, 如果想转换成int,重写model中的getInt方法: public Integer getInt( ...
- HT for Web列表和3D拓扑组件的拖拽应用
很多可视化编辑器都或多或少有一些拖拽功能,比如从一个List列表中拖拽一个节点到拓扑组件上进行建模,并且在拖拽的过程中鼠标位置下会附带一个被拖拽节点的缩略图,那么今天我们就来实现这样的拖拽效果. 首先 ...
- Java魔法堂:内部类详解
一.前言 对于内部类平时编码时使用的场景不多,比较常用的地方应该就是绑定事件处理程序的时候了(从C#.JS转向Java阵营的孩子总不不习惯用匿名内部类来做事件订阅:().本文将结合Bytecode对四 ...
- 【转载】GPU 加速下的图像处理
Instagram,Snapchat,Photoshop. 所有这些应用都是用来做图像处理的.图像处理可以简单到把一张照片转换为灰度图,也可以复杂到是分析一个视频,并在人群中找到某个特定的人.尽管这些 ...