美文网首页
requestAnimationFrame与setTimeout

requestAnimationFrame与setTimeout

作者: 209bd3bc6844 | 来源:发表于2017-06-14 18:01 被阅读0次

requestAnimationFrame

window.requestAnimationFrame() 这个方法是用来在页面重绘之前,通知浏览器调用一个指定的函数



相当一部分的浏览器的显示频率是16.7ms, 1m绘制60帧,就是上图第一行的节奏,表现就是“我和你一步两步三步四步往前走……”。如果我们火力搞猛一点,例如搞个10ms setTimeout,就会是下面一行的模样——每第三个图形都无法绘制(红色箭头指示),表现就是“我和你一步两步 坑 四步往前走……”。
requestAnimationFrame就是为了这个而出现的。我所做的事情很简单,跟着浏览器的绘制走,如果浏览设备绘制间隔是16.7ms,那我就这个间隔绘制;如果浏览设备绘制间隔是10ms, 我就10ms绘制。这样就不会存在过度绘制的问题,动画不会掉帧,自然流畅的说~~

(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));//上一次调用和下一次调用直接的间隔,timeToCall如果大于16.7就证明浏览器空闲没有在绘制,立刻插入执行绘制。timeToCall如果小于16.7。就用16.7减去上一次到这一次执行代码所用的实际。得到多少秒后可以插入执行。
            var id = window.setTimeout(function() {
                callback(currTime + timeToCall);
            }, timeToCall);
            lastTime = currTime + timeToCall;
            return id;
        };
    }
    if (!window.cancelAnimationFrame) {
        window.cancelAnimationFrame = function(id) {
            clearTimeout(id);
        };
    }
}());

调用requestAnimationFrame 一般都是递归调用实现绘制动画。

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会根据浏览器绘制的频率进行调用。
    };
    _run();
};

var i = 0;
function aa() {
    setTimeout(()=>{
        i++
        console.log(i)
    },1)
    if(i <= 11){
        aa()
    }
    
}
aa()

上面这个代码会造成死循环,为什么?
因为setTimeout是异步的,必须等待所有同步代码执行完成才会执行,这里的同步代码包括if(i <= 11){},但是i的值是在setTimeout才会被改变的。if这里的i就一直是0,所有造成了死循环,所有应该按照下面这种代码的逻辑书写。

function res (callback) {
    setTimeout(callback, 1000 / 60)
}
const startD = 0
function move() {
    console.log('sss');
    if(startD >=5){
        return;
    }
    startD++
    res(()=> {move()})
}
move()

requestAnimationFrame
从微信小程序重力感应 API 到 requestAnimationFrame 探索实现
Javascript高性能动画与页面渲染

相关文章

网友评论

      本文标题:requestAnimationFrame与setTimeout

      本文链接:https://www.haomeiwen.com/subject/pdgsqxtx.html