使用浏览器原生函数优化动画
2012-01-11 10:45
190 查看
Web中的JS动画原理并不复杂,JK前些时写过系列文章《动画组件(wagang版)》,讲解帧动画的原理以及QWrap版的实现,偷懒直接贴过来:
后来,一些浏览器推出各自私有Api提供动画管理,W3C也出了一份WindowAnimationTiming interface规范,定义了以下接口:
对 比文首JK总结的动画四要素,规范里少了一个帧间隔时间frameTime。这正是动画组件可以被优化的地方,原生实现里的frameTime被设计为可 根据CPU使用率、window是否被最小化、元素是否被隐藏等因素进行动态调整。浏览器可根据实际情况降低fps甚至停止动画。来看下新Api怎么用。
高版本webkit内核提供的webkitRequestAnimationFrame,跟规范非常接近,看一个示例:
expand source firefox 里也有类似的mozRequestAnimationFrame,不过非常坑爹的找不到对应的 mozCancelRequestAnimationFrame,幸好可以注册动画时不传动画函数,把动画函数绑定在moz私有的beforepaint 事件上,通过移除事件来移除动画:
expand source 代码还是很简单的。总结下,原生动画行为可以理解为:
请求第一帧动画,记录动画启动时间;
用回调函数第一个参数(当前时间),减去启动时间,除以动画时长(dur),得到进度(per);
根据per改变动画元素的一些属性,启动下一帧动画;
当per等于1时,结束动画。
实际上,这就是JK说的保时丢帧策略,dur是一定的,frameTime并不固定。这些示例实际测试中,在firefox5和最新chrome下fps都在62左右,也就是说frameTime在16ms左右。
剩下的工作就是各种封装了。月影实现的QWrap动画组件已经是封装好直接可用的,在gecko和webkit下都是用原生函数,对于没有原生动画的浏览器,使用setInterval进行统一帧管理。提供了常见的css动画、scroll动画和color动画,支持NodeW链式调用。附上地址:https://github.com/wedteam/qwrap-effect
最后,放上使用浏览器原生函数动画实现的组件:点击这里
参考:
Timing control for script-based animations
MDC:requestAnimationFrame
我们把动画抽象一下,它由以下几个组成部分:
时长(dur),即动画播放的时间总长。
进度(per),播放的进度,在区间[0,1]之内。
帧间隔时间(frameTime),即多长时间播放一帧。
动画函数(animFun),它是每一帧的渲染函数。定时器每隔frameTime来调用一下animFun(per)。也就是说按进度播放一帧动画。
这四个基本参数将动画抽象成为一个js类,系统的理解就是:
“在dur时间内,每隔frameTime时间,播放一次animFun(per)。”
随着页面上动画的使用越来越频繁,为了避免过多的定时器带来额外系统开销,一般的动画组件都会采用“统一帧管理”:只使用一个定时器,在每一动画帧依次调用所有注册的动画事件。时长(dur),即动画播放的时间总长。
进度(per),播放的进度,在区间[0,1]之内。
帧间隔时间(frameTime),即多长时间播放一帧。
动画函数(animFun),它是每一帧的渲染函数。定时器每隔frameTime来调用一下animFun(per)。也就是说按进度播放一帧动画。
这四个基本参数将动画抽象成为一个js类,系统的理解就是:
“在dur时间内,每隔frameTime时间,播放一次animFun(per)。”
后来,一些浏览器推出各自私有Api提供动画管理,W3C也出了一份WindowAnimationTiming interface规范,定义了以下接口:
[Supplemental, NoInterfaceObject]
interface WindowAnimationTiming {
long requestAnimationFrame(in FrameRequestCallback callback);
void cancelRequestAnimationFrame(in long handle);
};
Window implements WindowAnimationTiming;
[Callback, NoInterfaceObject]
interface FrameRequestCallback {
void sample(in DOMTimeStamp time);
};
注册动画使用requestAnimactionFrame函数,接受动画函数callback作为参数,并返回动画ID;移除动画使用cancelRequestAnimationFrame函数,参数是动画ID;动画函数执行时,会传入当前系统时间戳。interface WindowAnimationTiming {
long requestAnimationFrame(in FrameRequestCallback callback);
void cancelRequestAnimationFrame(in long handle);
};
Window implements WindowAnimationTiming;
[Callback, NoInterfaceObject]
interface FrameRequestCallback {
void sample(in DOMTimeStamp time);
};
对 比文首JK总结的动画四要素,规范里少了一个帧间隔时间frameTime。这正是动画组件可以被优化的地方,原生实现里的frameTime被设计为可 根据CPU使用率、window是否被最小化、元素是否被隐藏等因素进行动态调整。浏览器可根据实际情况降低fps甚至停止动画。来看下新Api怎么用。
高版本webkit内核提供的webkitRequestAnimationFrame,跟规范非常接近,看一个示例:
expand source firefox 里也有类似的mozRequestAnimationFrame,不过非常坑爹的找不到对应的 mozCancelRequestAnimationFrame,幸好可以注册动画时不传动画函数,把动画函数绑定在moz私有的beforepaint 事件上,通过移除事件来移除动画:
expand source 代码还是很简单的。总结下,原生动画行为可以理解为:
请求第一帧动画,记录动画启动时间;
用回调函数第一个参数(当前时间),减去启动时间,除以动画时长(dur),得到进度(per);
根据per改变动画元素的一些属性,启动下一帧动画;
当per等于1时,结束动画。
实际上,这就是JK说的保时丢帧策略,dur是一定的,frameTime并不固定。这些示例实际测试中,在firefox5和最新chrome下fps都在62左右,也就是说frameTime在16ms左右。
剩下的工作就是各种封装了。月影实现的QWrap动画组件已经是封装好直接可用的,在gecko和webkit下都是用原生函数,对于没有原生动画的浏览器,使用setInterval进行统一帧管理。提供了常见的css动画、scroll动画和color动画,支持NodeW链式调用。附上地址:https://github.com/wedteam/qwrap-effect
最后,放上使用浏览器原生函数动画实现的组件:点击这里
参考:
Timing control for script-based animations
MDC:requestAnimationFrame
相关文章推荐
- 前端性能优化:尽可能使用CSS动画
- 使用原生JS实现jQuery的addClass, removeClass, hasClass函数功能
- 使用原生JS实现jQuery的addClass, removeClass, hasClass函数功能
- 在QtOpenglWidget中使用原生函数写FBO时,应注意的
- 利用tween,使用原生js实现模块回弹动画效果
- 使用了 :before 等伪元素中的其中一个来做 animation 动画; 在 animation 动画改变了其中的某个 rem 的值; 在这样的前提下,又是使用有这个 bug 的版本浏览器,那么就
- 代码简洁优化的一点思考:函数参数的判断与return 语句的使用
- 使用jq和原生封装2个动画插件
- PHP使用原生函数实现文件上传及下载
- SQL Server 使用分区函数实现查询优化
- position relative 与 js 原生动画 浏览器兼容问题
- 前端性能优化:尽可能使用CSS动画
- Android使用原生动画工具类实现平移动画
- 超棒的跨浏览器纯CSS动画实现 Animate.css使用方法
- 使用开窗函数优化查询的一个案例
- Matlab优化函数linprog的使用
- JS原生动画函数封装
- 事件监听函数,跨浏览器使用
- yii 2.0 使用部分自带函数来优化代码
- JQuery 动画渲染函数animate使用心得