requestAnimationFrame 和setTimeou

2018-04-25  本文已影响17人  滚石_c2a6

setTimeoutsetInterval不同requestAnimationFrame不需要设置时间间隔。这有什么好处呢?为什么requestAnimationFrame被称为神器呢?本文将详细介绍HTML5新增的定时器requestAnimationFrame

引入

计时器一直是JavaScript动画的核心技术。而编写动画循环的关键是要知道延迟时间多长合适。一方面,循环间隔必须足够短,这样才能让不同的动画效果显得平滑流畅;另一方面,循环间隔还要足够长,这样才能确保浏览器有能力渲染产生的变化。

大多数电脑显示器的刷新频率是60Hz,大概相当于每秒钟重绘60次。大多数浏览器都会对重绘操作加以限制,不超过显示器的重绘频率,因为即使超过那个频率用户体验也不会有提升。因此,最平滑动画的最佳循环间隔是1000ms/60,约等于16.6ms

setTimeoutsetInterval的问题是,它们都不精确。它们的内在运行机制决定了时间间隔参数实际上只是指定了把动画代码添加到浏览器UI线程队列中以等待执行的时间。如果队列前面已经加入了其他任务,那动画代码就要等前面的任务完成后再执行。

requestAnimationFrame采用系统时间间隔,保持最佳绘制效率,不会因为间隔时间过短,造成过度绘制,增加开销;也不会因为间隔时间太长,使用动画卡顿不流畅,让各种网页动画效果能够有一个统一的刷新机制,从而节省系统资源,提高系统性能,改善视觉效果。

特点

使用

requestAnimationFrame的用法与setTimeout很相似,只是不需要设置时间间隔而已。requestAnimationFrame使用一个回调函数作为参数,这个回调函数会在浏览器重绘之前调用。它返回一个整数,表示定时器的编号,这个值可以传递给cancelAnimationFrame用于取消这个函数的执行。

requestID = requestAnimationFrame(callback); 

//控制台输出1和0
var timer = requestAnimationFrame(function(){
    console.log(0);
}); 
console.log(timer); // => 1

cancelAnimationFrame方法用于取消定时器:

//控制台什么都不输出
var timer = requestAnimationFrame(function(){
    console.log(0);
}); 

cancelAnimationFrame(timer);

也可以直接使用返回值进行取消:

var timer = requestAnimationFrame(function(){
    console.log(0);
}); 
cancelAnimationFrame(1);

著作权归作者所有。
商业转载请联系作者获得授权,非商业转载请注明出处。
原文: https://www.w3cplus.com/javascript/requestAnimationFrame.html © w3cplus.com

示例:

setTimeout <span id="time_st"></span>ms<br>
<div class="box"><div id="st" class="bar"></div></div>
<br>
requestAnimationFrame <span id="time_af"></span>ms<br>
<div class="box"><div id="af" class="bar"></div></div>
.box {
    width: 300px;
    height: 20px;
    text-align: left;
    border: 3px solid #000000;
}

.bar {
    width: 0px;
    height: 100%;
    background-color: #999999;
}
window.requestAnimFrame = (function(){
  return  window.requestAnimationFrame       ||
          window.webkitRequestAnimationFrame ||
          window.mozRequestAnimationFrame    ||
          window.oRequestAnimationFrame      ||
          window.msRequestAnimationFrame     ||
          function(/* function */ callback, /* DOMElement */ element){
            window.setTimeout(callback, 1000 / 60);
          };
})();

var start_time = (new Date()).getTime();

var st = {
    $elm: $('#st'),
    len: 0,
    $disp: $('#time_st')
};
var af = {
    $elm: $('#af'),
    len: 0,
    $disp: $('#time_af')
};

function heavy_process(){
    var stoptime = 8; 
    var start = (new Date()).getTime();
    while((new Date()).getTime() - start < stoptime){
        // sleep
    }
}

function render(obj){
    heavy_process();
    obj.$elm.css('width', obj.len +'px');
    obj.len += 1;
    if(obj.len > 300){
        obj.$disp.text((new Date()).getTime() - start_time);
        return false;
    }
    return true;
}

(function st_loop(){
    if( !render(st) ){
        return false;
    }
    setTimeout(st_loop, 16.667);
}());
(function af_loop(){
    if( !render(af) ){
        return false;
    }
    requestAnimFrame(af_loop);
}());

转自:http://jsfiddle.net/calpo/H7EEE/

上一篇下一篇

猜你喜欢

热点阅读