本文翻译自:https://css-tricks.com/using-requestanimationframe/ ,如有侵权,请联系我!
引入
以前JavaScript只有一种时间间隔循环的方式:setInterval()
。如果你需要以特别快的速度(不是像for循环那样极致快)重复一些内容,你可以使用setInterval()
。如果用在动画上,让动画和屏幕刷新速度一致(大多数认为60Hz,也就是一秒钟60次),动画就会显得非常流畅,我们以前是这样解决的:
setInterval(function() {
// animiate something
}, 1000/60);
然而,现在有了更好的替代方案。Paul Irish 两年前推荐使用requestAnimationFrame
,我以前不重视这个方法,现在我用完以后觉得很舒服,还推荐给我的成家班用。
好用在哪?
Paul 是这样解释的:
1、浏览器会优化它,所以动画会显得更顺滑;
2、动画在 不活动的浏览器标签 会自动暂停,节省CPU;
3、对电池更加友好;
尽量简单的例子:
function repeatOften() {
// Do whatever
requestAnimationFrame(repeatOften);
}
requestAnimationFrame(repeatOften);
调用一次(最后一行语句就是),这个方法就会自己开始递归了。
动画的开始和暂停:
和我们的setTimeout
、setInterval
一样,requestAnimationFrame
也会返回一个定时器ID,下面用jQuery小小地演示一下(博主注:这里和传统定时器一样,也会有多次点击多次添加定时器的毛病):
var globalID; //requestAnimationFrame定时器的ID
function repeatOften() {
$("<div />").appendTo("body"); //动画变换本体,你也可以变换width、transform、scrollTop等等,这里是每次添加一个div盒子
globalID = requestAnimationFrame(repeatOften); //递归循环调用,
}
$("#start").on("click", function() {
globalID = requestAnimationFrame(repeatOften);
});
$("#stop").on("click", function() {
cancelAnimationFrame(globalID);
});
这个例子的实现是这样的(实际上很流畅,录制有点不好):
浏览器支持情况:
Can I use 可以找到。
使用之前建议加上兼容Polyfill(包括不同浏览器的不同表达方式以及不支持此方法的替代方法):
(function() {
var lastTime = 0;
var vendors = ['ms', 'moz', 'webkit', 'o'];
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'];
}
if (!window.requestAnimationFrame)
window.requestAnimationFrame = function(callback, element) {
var currTime = new Date().getTime();
var timeToCall = Math.max(0, 16 - (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);
};
}());
PS:收帝都工作机会 ,感谢!