动画requestAnimationFrame
前言
在研究canvas的2D pixi.js库的时候,其动画的刷新都用requestAnimationFrame替代了setTimeout 或 setInterval
但是jQuery中还是采用了setInterval,我这章就研究下顺便改造下jQuery的动画
定时器
jQuery动画的实现考虑到兼容与易用性采用了setInterval来不断绘制新的属性值,从而达到动画的效果。
大部分浏览器的显示频率是16.7ms,由于浏览器的特性,setInterval会有一个丢帧的问题
即使向其传递毫秒为单位的参数,它们也不能达到ms的准确性。这是因为javascript是单线程的,可能会发生阻塞
jQuery会有一个全局设置jQuery.fx.interval = 13 设置动画每秒运行帧数。
默认是13毫秒。该属性值越小,在速度较快的浏览器中(例如,Chrome),动画执行的越流畅,但是会影响程序的性能并且占用更多的 CPU 资源
那么归纳一点最关键的问题:
开发着并不知道下一刻绘制动画的最佳时机是什么时候
requestAnimationFrame
requestAnimationFrame 是专门为实现高性能的帧动画而设计的一个API
说简单点
- setInterval、setTimeout是开发者主动要求浏览器去绘制,但是由于种种问题,浏览器可能会漏掉部分命令
- requestAnimationFrame 就是浏览器什么要开始绘制了浏览器自己知道,通过requestAnimationFrame 告诉开发者,这样就不会出现重复绘制丢失的问题了
目前已在多个浏览器得到了支持,包括IE10+,Firefox,Chrome,Safari,Opera等,在移动设备上,ios6以上版本以及IE mobile 10以上也支持requestAnimationFrame,
唯一比较遗憾的是目前安卓上的原生浏览器并不支持requestAnimationFrame,不过对requestAnimationFrame的支持应该是大势所趋了,安卓版本的chrome 16+也是支持requestAnimationFrame的。
比较
区别:
- requestAnimationFrame 会把每一帧中的所有DOM操作集中起来,在一次重绘或回流中就完成,并且重绘或回流的时间间隔紧紧跟随浏览器的刷新频率,一般来说,这个频率为每秒60帧
- 隐藏或不可见的元素中,requestAnimationFrame将不会进行重绘或回流,这当然就意味着更少的的cpu,gpu和内存使用量。
- requestAnimationFrame也会像setTimeout一样有一个返回值ID用于取消,可以把它作为参数传入cancelAnimationFrame函数来取消requestAnimationFrame的回调
兼容处理
摘自HTML5 Canvas 核心技术
window.requestNextAnimationFrame = (function () {
var originalWebkitRequestAnimationFrame = undefined,
wrapper = undefined,
callback = undefined,
geckoVersion = ,
userAgent = navigator.userAgent,
index = ,
self = this;
// Workaround for Chrome 10 bug where Chrome
// does not pass the time to the animation function
if (window.webkitRequestAnimationFrame) {
// Define the wrapper
wrapper = function (time) {
if (time === undefined) {
time = +new Date();
}
self.callback(time);
};
// Make the switch
originalWebkitRequestAnimationFrame = window.webkitRequestAnimationFrame;
window.webkitRequestAnimationFrame = function (callback, element) {
self.callback = callback;
// Browser calls the wrapper and wrapper calls the callback
originalWebkitRequestAnimationFrame(wrapper, element);
}
}
// Workaround for Gecko 2.0, which has a bug in
// mozRequestAnimationFrame() that restricts animations
// to 30-40 fps.
if (window.mozRequestAnimationFrame) {
// Check the Gecko version. Gecko is used by browsers
// other than Firefox. Gecko 2.0 corresponds to
// Firefox 4.0.
index = userAgent.indexOf('rv:');
if (userAgent.indexOf('Gecko') != -) {
geckoVersion = userAgent.substr(index + , );
if (geckoVersion === '2.0') {
// Forces the return statement to fall through
// to the setTimeout() function.
window.mozRequestAnimationFrame = undefined;
}
}
}
return window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function (callback, element) {
var start,
finish;
window.setTimeout(function () {
start = +new Date();
callback(start);
finish = +new Date();
self.timeout = / - (finish - start);
}, self.timeout);
};
}());
window.cancelNextRequestAnimationFrame = window.cancelRequestAnimationFrame
|| window.webkitCancelAnimationFrame
|| window.webkitCancelRequestAnimationFrame
|| window.mozCancelRequestAnimationFrame
|| window.oCancelRequestAnimationFrame
|| window.msCancelRequestAnimationFrame
|| clearTimeout;
对比
通过requestAnimationFrame与setInterval同样的效果对比
一段动画采用setInterval与requestAnimationFrame,分别给出了webKit下调用刷新的次数
setInterval实现,调用了144次左右
<!doctype html><img id="book" style="background:red;opacity:1;position: relative; left: 500px;" alt="" width="100" height="123" data-mce-style="background: red; opacity: 1; position: relative; left: 500px;" /><div id="several"><br /></div><script type="text/javascript">
var book = document.getElementById('book')
var several = document.getElementById('several');
animate(book, {
left: 50,
duration: 2000
})
function animate(elem, options){
//动画初始值
var start = 500
//动画结束值
var end = options.left
//动画id
var timerId;
var createTime = function(){
return (+new Date)
}
//动画开始时间
var startTime = createTime();
var i = 0;
function tick(){
i++;
several.innerHTML = 'setInterval调用次数:' + i;
//每次变化的时间
var remaining = Math.max(0, startTime + options.duration - createTime())
var temp = remaining / options.duration || 0;
var percent = 1 - temp;
var stop = function(){
//停止动画
clearInterval(timerId);
timerId = null;
}
var setStyle = function(value){
elem.style['left'] = value + 'px'
}
//移动的距离
var now = (end - start) * percent + start;
if(percent === 1){
setStyle(now)
stop();
}else{
setStyle(now)
}
}
//开始执行动画
var timerId = setInterval(tick, 13);
}
</script>
requestAnimationFrame 实现调用了120次左右
<!doctype html><img id="book" style="background:red;opacity:1;position: relative; left: 500px;" alt="" width="100" height="123" data-mce-style="background: red; opacity: 1; position: relative; left: 500px;" /><div id="several"><br /></div><script type="text/javascript">
var book = document.getElementById('book')
var several = document.getElementById('several');
animate(book, {
left: 50,
duration: 2000
})
function animate(elem, options){
//动画初始值
var start = 500
//动画结束值
var end = options.left
var createTime = function(){
return (+new Date)
}
//动画开始时间
var startTime = createTime();
var timerId;
//开始动画
var startAnim = function() {
timerId = requestAnimationFrame(tick,15);
}
//停止动画
var stopAnim = function() {
cancelAnimationFrame(timerId)
}
var i = 0;
function tick(){
i++;
several.innerHTML = 'requestAnimationFrame调用次数:' + i;
//每次变化的时间
var remaining = Math.max(0, startTime + options.duration - createTime())
var temp = remaining / options.duration || 0;
var percent = 1 - temp;
var setStyle = function(value){
elem.style['left'] = value + 'px'
}
//移动的距离
var now = (end - start) * percent + start;
if(percent === 1){
setStyle(now)
stopAnim() ;
}else{
setStyle(now)
startAnim(tick);
}
}
//开始执行动画
startAnim(tick);
}
</script>
通过对比,在同样的时间里,通过定时器刷新的次数是要更多,当然定时器跟设置的时间是有关系的
这里我要强调一点,有效值,就是我们在浏览器能接受的范围内,给出一个最佳的渲染时间,这样才是一个性能优化的最佳的选择
动画requestAnimationFrame的更多相关文章
- 移动端动画——requestAnimationFrame
window.requestAnimationFrame() 告诉浏览器--你希望执行一个动画,并且要求浏览器在下次重绘之前调用指定的回调函数更新动画.该方法需要传入一个回调函数作为参数,该回调函数会 ...
- requestAnimationFrame的用法
该方法用于在浏览器中制作动画.通过递归调用同一方法来不断更新画面以达到动起来的效果,但它优于setTimeout/setInterval的地方在于它是由浏览器专门为动画提供的API,在运行时浏览器会自 ...
- h5编写帧动画
var requestAnimationFrame = window.requestAnimationFrame || window.webkitRequestAnimationFrame; var ...
- H5实现摇一摇技术总结
摇一摇遇到的问题 一.如何对摇晃效果进行反馈 刚开始的处理方式是,摇晃过程中不做任何处理,但后来反馈说这种效果不好,好像就没有摇动一样,如果声音也不响的话,就真的和什么都没发生一样. 后来想了想,加入 ...
- 浏览器-04 WebKit 渲染2
渲染主循环(main loop)和requestAnimationFrame requestAnimationFrame 使用requestAnimationFrame而非setTimeout/set ...
- H5摇一摇遇到的问题
一.如何对摇晃效果进行反馈 刚开始的处理方式是,摇晃过程中不做任何处理,但后来反馈说这种效果不好,好像就没有摇动一样,如果声音也不响的话,就真的和什么都没发生一样. 后来想了想,加入摇晃过程动画,就像 ...
- 【WebGL】《WebGL编程指南》读书笔记——第4章
一.前言 今天继续第四章的学习内容,开始学习复合变换的知识. 二.正文 Example1: 复合变换 在书中,作者为我们封装了一套用于变换的矩阵对象:Matrix4对象.它 ...
- 【带着canvas去流浪(7)】绘制水球图
目录 一. 任务说明 二. 重点提示 三. 示例代码 四. 文字淹水效果的实现 五. 关于canvas抗锯齿 六. 小结 示例代码托管在:http://www.github.com/dashnowor ...
- 浏览器根对象window之操作方法
1.1 不常用 alert:带有一条指定消息和一个OK按钮的警告框. confirm:带有指定消息和OK及取消按钮的对话框. prompt:可提示用户进行输入的对话框. print:打印网页. ope ...
随机推荐
- HTML渲染过程详解
无意中看到寒冬关于前端的九个问题,细细想来我也只是对第一.二.九问有所了解,正好也趁着这个机会梳理一下自己的知识体系.由于本人对http协议以及dns对url的解析问题并不了解,所以这里之探讨url请 ...
- 高大上的微服务可以很简单,使用node写微服务
安装 npm install m-service --save 使用 编写服务处理函数 // dir1/file1.js // 使用传入的console参数输出可以自动在日志里带上request id ...
- Content Security Policy 入门教程
阮一峰文章:Content Security Policy 入门教程
- PHP-解析验证码类--学习笔记
1.开始 在 网上看到使用PHP写的ValidateCode生成验证码码类,感觉不错,特拿来分析学习一下. 2.类图 3.验证码类部分代码 3.1 定义变量 //随机因子 private $char ...
- input标签中button在iPhone中圆角的问题
1.问题 使用H5编写微信页面时,使用<input type="button"/>时,在Android手机中显示正常,但是在iPhone手机中则显示不正常,显示为圆角样 ...
- jquery.cookie的使用
今天想到了要为自己的影像日记增加赞的功能,并且需要用到cookie. 记得原生的js操作cookie也不是很麻烦的,但似乎jquery更简单,不过相比原生js,需要额外引入2个文件,似乎又不是很好,但 ...
- 微信小程序开发—快速掌握组件及API的方法
微信小程序框架为开发者提供了一系列的组件和API接口. 组件主要完成小程序的视图部分,例如文字.图片显示.API主要完成逻辑功能,例如网络请求.数据存储.音视频播放控制,以及微信开放的微信登录.微信支 ...
- 【干货分享】流程DEMO-外出申请
流程名: 外出申请 流程相关文件: 流程包.xml 流程说明: 直接导入流程包文件,即可使用本流程 表单: 流程: 图片:2.png DEMO包下载: http://files.cnblog ...
- oracle 误删数据恢复
1.根据时间点查系统版本号scn: select timestamp_to_scn(to_timestamp('2013-01-07 11:20:00','YYYY-MM-DD HH:MI:SS')) ...
- [转] 从知名外企到创业公司做CTO是一种怎样的体验?
这是我近期接受51CTO记者李玲玲采访的一篇文章,分享给大家. 作者:李玲玲来源:51cto.com|2016-12-30 15:47 http://cio.51cto.com/art/201612/ ...