一、小谈 requestAnimationFrame:

说起 requestAnimationFrame,我们先看幅图:

相当一部分的浏览器的显示频率是16.7ms, 就是上图第一行的节奏,表现就是“我和你一步两步三步四步往前走……”。如果我们火力搞猛一点,例如搞个10ms setTimeout,就会是下面一行的模样——每第三个图形都无法绘制(红色箭头指示),表现就是“我和你一步两步 坑四步往前走……”。

想象国庆北京高速,最多每16.7s通过一辆车,结果,突然插入一批 setTimeout的军车,强行要10s通过。显然,这是超负荷的,要想顺利进行,只能让第三辆车直接消失(正如显示绘制第三帧的丢失)。然,这是不现实的,于是就有了会堵车!

同样的,显示器16.7ms刷新间隔之前发生了其他绘制请求(setTimeout),导致所有第三帧丢失,继而导致动画断续显示(堵车的感觉),这就是过度绘制带来的问题。不仅如此,这种计时器频率的降低也会对电池使用寿命造成负面影响,并会降低其他应用的性能。

这也是为何setTimeout的定时器值推荐最小使用16.7ms的原因(16.7 = 1000 / 60, 即每秒60帧)。

而我requestAnimationFrame就是为了这个而出现的。它所做的事情很简单,跟着浏览器的绘制走,如果浏览设备绘制间隔是16.7ms,那我就这个间隔绘制;如果浏览设备绘制间隔是10ms, 我就10ms绘制。这样就不会存在过度绘制的问题,动画不会掉帧,自然流畅的说~~

内部是这么运作的:
浏览器(如页面)每次要洗澡(重绘),就会通知我(requestAnimationFrame):小丸子,我要洗澡了,你可以跟我一起洗哦!

这是资源非常高效的一种利用方式。怎么讲呢?

  1. 就算很多个小丸子要一起洗澡,浏览器只要通知一次就可以了。而setTimeout貌似是多个独立绘制。
  2. 页面最小化了,或者被Tab切换关灯了。页面是不会洗澡的,自然,小丸子也不会洗澡的(没通知啊)。页面绘制全部停止,资源高效利用。

二、兼容性:

所以,requestAnimationFrame 一个简单的兼容性代码如下:

(function() {
var lastTime = 0;
var vendors = ['webkit', 'moz'];
for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
window.requestAnimationFrame = window[vendors[x] + 'RequestAnimationFrame'];
window.cancelAnimationFrame = window[vendors[x] + 'CancelAnimationFrame'] || // Webkit中此取消方法的名字变了
window[vendors[x] + 'CancelRequestAnimationFrame'];
} if (!window.requestAnimationFrame) {
window.requestAnimationFrame = function(callback, element) {
var currTime = new Date().getTime();
var timeToCall = Math.max(0, 16.7 - (currTime - lastTime));
var id = window.setTimeout(function() {
callback(currTime + timeToCall);
}, timeToCall);
lastTime = currTime + timeToCall;
return id;
};
}
if (!window.cancelAnimationFrame) {
window.cancelAnimationFrame = function(id) {
clearTimeout(id);
};
}
}());

三、动画效果:

css3 可以实现很多动画效果,贝塞尔曲线是一个标准3次方曲线(详见:贝塞尔曲线与CSS3动画、SVG和canvas的基情),因此,只能是:LinearSineQuadCubicExpo等,如下图:

但 css3 对于 BackBounce等缓动则只可观望而不可亵玩焉。

先看一个效果:小球弹起落地效果 (此例结合了 Tweenjs 库)

动画核心代码如下:

funFall = function() {
var start = 0, during = 100;
var _run = function() {
start++;
var top = Tween.Bounce.easeOut(start, objBall.top, 500 - objBall.top, during);
ball.css("top", top);
shadowWithBall(top); // 投影跟随小球的动
if (start < during) requestAnimationFrame(_run);
};
_run();
};

四、深究 requestAnimationFrame:

事件循环和任务队列机制里边,牵扯到 setTimeout,在讨论浏览器刷新频率的时候,经常将 setTimeout和 requestAnimationFarme作比较。

那么,requestAnimationFarme是否也属于异步任务,如果是的话,是属于macro-task还是micro-task?

关于macro-task 和 micro-task:

1、macrotasks包含:主js、UI渲染、setTimeout、setInterval、setImmediate、requestAnimationFarme、I/O等
2、microtasks包含:process.nextTick、promise、Object.observe等

具体详见:

从Promise来看JavaScript中的Event Loop、Tasks和Microtasks

理解事件循环一(浅析)

Promise的队列与setTimeout的队列有何关联

参考链接:https://www.zhangxinxu.com/wordpress/2013/09/css3-animation-requestanimationframe-tween-%e5%8a%a8%e7%94%bb%e7%ae%97%e6%b3%95/

关于 requestAnimationFrame 小结的更多相关文章

  1. requestAnimationFrame小结

    背景 在Web应用中,实现动画效果的方法比较多,Javascript 中可以通过定时器 setTimeout或者setInterval 来实现,css3 可以使用 transition 和 anima ...

  2. 3月web前端面试小结

    说一下box-sizing的应用场景 box-sizing的属性值分为两个,border-box和content-box,其中, border-box:width=content+padding+bo ...

  3. 神奇的requestAnimationFrame解决传统定时器bug

    可能你还没见过这个东西是个啥,其实他就是类似于setTimeout和setInterval,然而它与setTimeout和setInterval又有所不同,requestAnimationFrame不 ...

  4. 小程序刷新webview小结

    场景 在小程序其它页面做了操作,数据发生改变,回到webview页面时需要更新webview里面的数据.由于小程序没有提供与webview的实时通信能力,因此刷新页面是个可考虑的做法. 方法一 最常见 ...

  5. 动画requestAnimationFrame

    前言 在研究canvas的2D pixi.js库的时候,其动画的刷新都用requestAnimationFrame替代了setTimeout 或 setInterval 但是jQuery中还是采用了s ...

  6. 从零开始编写自己的C#框架(26)——小结

    一直想写个总结,不过实在太忙了,所以一直拖啊拖啊,拖到现在,不过也好,有了这段时间的沉淀,发现自己又有了小小的进步.哈哈...... 原想框架开发的相关开发步骤.文档.代码.功能.部署等都简单的讲过了 ...

  7. Python自然语言处理工具小结

    Python自然语言处理工具小结 作者:白宁超 2016年11月21日21:45:26 目录 [Python NLP]干货!详述Python NLTK下如何使用stanford NLP工具包(1) [ ...

  8. java单向加密算法小结(2)--MD5哈希算法

    上一篇文章整理了Base64算法的相关知识,严格来说,Base64只能算是一种编码方式而非加密算法,这一篇要说的MD5,其实也不算是加密算法,而是一种哈希算法,即将目标文本转化为固定长度,不可逆的字符 ...

  9. iOS--->微信支付小结

    iOS--->微信支付小结 说起支付,除了支付宝支付之外,微信支付也是我们三方支付中最重要的方式之一,承接上面总结的支付宝,接下来把微信支付也总结了一下 ***那么首先还是由公司去创建并申请使用 ...

随机推荐

  1. SAS学习笔记49 生成前20个黄金分割数列到数据集

    黄金分割数列即斐波那契数列,该数列中后一个数与前一个数的比例越往后越接近于黄金比例(1+√5)/2 ,此数列分布表现出极致的均衡与和谐之美

  2. oracle-3-Linux-11g安装-静默安装

    oracle下载地址:https://www.oracle.com/database/technologies/112010-linx8664soft.html 系统是最小化安装的Centos7.2 ...

  3. Student's Camp CodeForces - 708E (dp,前缀和优化)

    大意: $n$行$m$列砖, 白天左侧边界每块砖有$p$概率被摧毁, 晚上右侧边界有$p$概率被摧毁, 求最后上下边界连通的概率. 记${dp}_{i,l,r}$为遍历到第$t$行时, 第$t$行砖块 ...

  4. Tomcat一闪而过的调试方法

    很少用tomcat来部署,都是用springboot微服务.只是以前学的时候搞demo试过而已. 软件测试的期末作业要求要测一个Javaweb的项目,给了一个包然后要求部署在tomcat中并启动. 然 ...

  5. logback日志无法按日期分割的问题

    发现在线上的时候,日志无法按日期分割的问题,所有日志都在第一天部署的那个日期的文件里面. 背景是Springboot + logback 原因是: 之前是: 用timeBaseRollingPolic ...

  6. java.lang.RuntimeException: Unable to instantiate activity ComponentInfo异常解决

    不能实例化activity有如下三种情况: 1.没有在Manifest.xml 清单中注册该activity,或者在创建完activity后,修改了包名或者activity的类名,而配置清单中没有修改 ...

  7. hdu 1075 map的使用 字符串截取的常用手段 以及string getline 使用起来的注意事项

    首先说字符串的截取套路吧 用坐标一个一个的输入 用遍历的方式逐个去检查字符串中的字符是否为符合的情况 如果是的话 把该字符放入截取string 中 让后坐标前移 如果不是的话 截取结束 坐标初始化 然 ...

  8. LINUX CGROUP总结

    简介: Linux CGroup全称Linux Control Group, 是Linux内核的一个功能,用来限制,控制与分离一个进程组群的资源(如CPU.内存.磁盘输入输出等).这个项目最早是由Go ...

  9. Oracle触发器编译错误及解决方案

    错误 TRIGGER **** 编译错误 错误:PLS-00103: 出现符号 "END"在需要下列之一时:        ( begin case declare exit    ...

  10. Dev GridControl 子集合标题

    显示效果: 设置: this.gridView3.OptionsView.ShowViewCaption = true; this.gridView3.ViewCaption = "资产明细 ...