记得当 requestAnimationFrame 出现时我立马就石更了,就跟初次玩耍 transition 时一样,欣喜若狂...

然后,然后特么的就懵逼了,这明明就是口挖不通的深井呀(如果是我傻,那我认了...)

一. 简介

随着页面上动画的使用越来越频繁,为了避免过多的定时器带来额外系统开销,一般的动画组件都会采用“统一帧管理”:只使用一个定时器,在每一动画帧依次调用所有注册的动画事件。

后来,一些浏览器推出各自私有Api提供动画管理,W3C也出了一份 WindowAnimationTiming interface 规范,也就是 requestAnimationFrame。

动画四要素: 时长(dur),即动画播放的时间总长。 进度(per),播放的进度,在区间 [0,1] 之内。 帧间隔时间(frameTime),即多长时间播放一帧。 动画函数(animFun),它是每一帧的渲染函数。

对动画优化而言,最需考虑的就是帧间隔时间 frameTime。

原生实现里的 frameTime 被设计为可根据 CPU 使用率、window 是否被最小化、元素是否被隐藏等因素进行动态调整。

浏览器可根据实际情况降低 fps 甚至停止动画。这比以前的 setTimeout 和 setInterval 不知道好到哪里去了。

二. 实践

简单点来讲:

注册动画使用 requestAnimactionFrame 函数,接受动画函数callback作为参数,并返回动画ID;

移除动画使用 cancelRequestAnimationFrame 函数,参数是动画ID;

动画函数执行时,会传入当前系统时间戳。

function timeout(dur, animFun, callback) {
var nowTime, Timer, duration;
function _run() {
var per = Math.min(1.0, (Date.now() - nowTime) / duration);
if (per >= 1) {
_stop();
if (callback) callback.call(this, duration);
} else {
if (animFun) animFun.call(this, per, duration);
Timer = window.requestAnimationFrame(_run);
}
}
function _start() {
_go(dur); return this;
}
function _go(dur) {
duration = dur, nowTime = Date.now(), _run(); return this;
}
function _stop() {
window.cancelAnimationFrame(Timer); return this;
}
return {
start: _start, stop: _stop, go: _go,
};
} var start = Date.now();
timeout(1000, function(per, dur){
var offset = 500 * per + 0;
if (per < 1) console.log('方块将从 0 移动' + offset + 'px 到 500');
}, function() {
console.log(Date.now() - start);
}).start();

三. 遗留的问题

在进行每一秒运行一次的倒计时会误差很严重,并不是标准的一秒。

这源于 requestAnimactionFrame 的智能,会根据现有性能进行的速率调整....虽然很好,但好尴尬呀...

上文说到,“动画函数执行时,会传入当前系统时间戳”,这句话并不可信,

因为 webkitRequestAnimationFrame 是可以的,但 requestAnimactionFrame 不对。

其次, firefox 里有 mozRequestAnimationFrame,却没有对应的 mozCancelRequestAnimationFrame,非常坑爹...

所以得这样 window.removeEventListener('MozBeforePaint', animFun, false);

开始还跟同事说它很牛逼牛逼呀,现在啪啪打脸,还得保持微笑,因为它是如此的令人期待...

最新文章

  1. Java学习笔记(三)
  2. uwsgi出现invalid request block size: 21573 (max 4096)...skip解决办法
  3. PHP生成二维码图片
  4. Elasticsearch 之 数据索引
  5. 《Java程序设计》第3周学习总结
  6. POJ 1317
  7. 构建项目AppFuse+QuickStart
  8. 字符(汉子)转换为ASCII
  9. PHP实现简单爬虫
  10. 第一章 工欲善其事 其利润—Android SDK工具(2)
  11. C#中 如何执行带GO的sql 语句
  12. yaf学习之——生成yaf示例框架
  13. 风火轮SMC532使用
  14. Entity Framework Code First 学习日记(1)精
  15. iOS学习之Object-C语言属性和点语法(转载收集)
  16. js中如何优雅的写if判断
  17. 通达OA数据库优化方案之_历史数据清理
  18. Java删除ArrayList中的重复元素
  19. AI-人工智能-参考文档
  20. [转帖]Docker五种存储驱动原理及应用场景和性能测试对比

热门文章

  1. 这是一篇markdown测试博客
  2. Tensorflow如何选择GPU
  3. Windows之建立C++开发环境
  4. 强大的find命令
  5. 分享一个编译期输出TODO,FIXME列表的宏
  6. ios 蓝牙相关
  7. Android无线测试之—UiAutmator运行命令介绍与快速调试
  8. using 关键字的使用
  9. 【BZOJ2226】[Spoj 5971] LCMSum 莫比乌斯反演(欧拉函数?)
  10. 《从零开始学Swift》学习笔记(Day 51)——扩展构造函数