大部分浏览器的显示频率为什么是16.7ms?
因为浏览器的刷新频率为每秒 60 帧 ,1 秒=1000 毫秒, 1000/60=16.7ms
浏览器出现丢帧现象的原因?
假如开一个10ms 的setTimeout,也就是 30ms 绘制 3 次,但是浏览器本来是 16.7ms 绘制一次,在 30 秒内只能绘制两次。那么就会造成丢帧的现象。(本来 30ms 要绘制 3 次,结果只只绘制了 2 次,丢了一帧),继而导致动画断续显示(堵车的感觉),这就是过度绘制带来的问题。也是 setTimeout 的定时器值推荐最小使用16.7ms的原因。
浏览器丢帧会造成什么问题?
- 导致动画断续显示
- 过度绘制会对电池使用寿命造成负面影响,并会降低其他应用的性能
描述一下运行机制?
-
requestAnimationFrame 会把每一帧中的所有 DOM 操作集中起来,在一次重绘或回流中就完成,并且重绘或回流的时间间隔紧紧跟随浏览器的刷新频率,一般来说,这个频率为每秒 60 帧
-
在隐藏或不可见的元素中,requestAnimationFrame 将不会进行重绘或回流,这当然就意味着更少的的 cpu,gpu 和内存使用量
用法?
- requestAnimationFrame 调用一下 只走一次,若要形成动画需要递归调用。
- 参数:动画的回调函数
- 返回值:id 动画帧编号
- 清除动画 cancelAnimationFrame(id)
let timer = 0
function move() {
if (true) {
cancelAnimationFrame(timer)
} else {
timer = requestAnimationFrame(move)
}
}
move()
与css 动画哪个性能更好?
没有做过比较,只能说两者不相上下。
兼容性如何?
IE10+,Firefox,Chrome,Safari,Opera 等,在移动设备上,ios6 以上版本以及 IE mobile 10 以上支持 requestAnimationFrame,唯一比较遗憾的是目前安卓上的原生浏览器并不支持 requestAnimationFrame,不过对 requestAnimationFrame 的支持应该是大势所趋了,安卓版本的 chrome 16+也是支持 requestAnimationFrame 的
如何兼容浏览器(即使ie6也能支持)?
(function () {
// 兼容webkit,moz内核
window.requestAnimationFrame = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame;
//取消动画帧有两个版本 cancelAnimationFrame, cancelRequestAnimationFrame
window.cancelAnimationFrame = window.cancelAnimationFrame || window.webkitCancelAnimationFrame || window.mozCancelAnimationFrame || window.cancelRequestAnimationFrame || window.webkitCancelRequestAnimationFrame || window.mozCancelRequestAnimationFrame;
if (!window.requestAnimationFrame) {
// setTimeout模拟动画帧
var lastTime = Date.now(); // 时间戳
window.requestAnimationFrame = function (callback) {
var id;
var nowTime = Date.now();
//并不是所有浏览器的屏幕的渲染频率为16.7,如果上一次的时间 和 本次时间 执行的间隔大于 16.7,那就不再延迟直接执行
var delay = Math.max(16.7 - (nowTime - lastTime), 0);
id = setTimeout(callback, delay);
lastTime = nowTime + delay; //上一次动画执行的时间
return id;
};
}
// 取消动画帧
if (!window.cancelAnimationFrame) {
window.cancelAnimationFrame = function (id) {
clearTimeout(id);
};
}
})();
升级版
(function () {
var lastTime = 0;
var vendors = ['webkit', 'moz'];
// 在for循环当中做判断 !window.requestAnimationFrame
for (var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
// 如果没值,直接赋值
window.requestAnimationFrame = window[vendors[x] + 'RequestAnimationFrame'];
window.cancelAnimationFrame =
window[vendors[x] + 'CancelAnimationFrame'] || window[vendors[x] + 'CancelRequestAnimationFrame'];
}
// setTimeout模拟动画帧
if (!window.requestAnimationFrame){
window.requestAnimationFrame = function (callback) {
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);
};
}
}());