定时器系列-被誉为神器的requestAnimationFrame

xiaoxiao2021-02-28  86

这里我需要引用下原作者的文章。http://www.cnblogs.com/xiaohuochai/p/5777186.html

   大多数电脑显示器的刷新频率是60Hz,大概相当于每秒钟重绘60次。大多数浏览器都会对重绘操作加以限制,不超过显示器的重绘频率,因为即使超过那个频率用户体验也不会有提升。因此,最平滑动画的最佳循环间隔是1000ms/60,约等于16.6ms   而setTimeout和setInterval的问题是,它们都不精确。它们的内在运行机制决定了时间间隔参数实际上只是指定了把动画代码添加到浏览器UI线程队列中以等待执行的时间。如果队列前面已经加入了其他任务,那动画代码就要等前面的任务完成后再执行 requestAnimationFrame采用系统时间间隔,保持最佳绘制效率,不会因为间隔时间过短,造成过度绘制,增加开销;也不会因为间隔时间太长,使用动画卡顿不流畅,让各种网页动画效果能够有一个统一的刷新机制,从而节省系统资源,提高系统性能,改善视觉效果。 特点   【1】requestAnimationFrame会把每一帧中的所有DOM操作集中起来,在一次重绘或回流中就完成,并且重绘或回流的时间间隔紧紧跟随浏览器的刷新频率   【2】在隐藏或不可见的元素中,requestAnimationFrame将不会进行重绘或回流,这当然就意味着更少的CPU、GPU和内存使用量   【3】requestAnimationFrame是由浏览器专门为动画提供的API,在运行时浏览器会自动优化方法的调用,并且如果页面不是激活状态下的话,动画会自动暂停,有效节省了CPU开销 使用   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); 兼容   IE9-浏览器不支持该方法,可以使用setTimeout来兼容 【简单兼容】 if (!window.requestAnimationFrame) { requestAnimationFrame = function(fn) { setTimeout(fn, 17); }; } 【严格兼容】 复制代码 if(!window.requestAnimationFrame){ var lastTime = 0; 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); }; } 应用   现在分别使用setInterval、setTimeout和requestAnimationFrame这三个方法制作一个简单的进制度效果 【1】setInterval 复制代码 <div id="myDiv" style="background-color: lightblue;width: 0;height: 20px;line-height: 20px;">0%</div> <button id="btn">run</button> <script> var timer; btn.onclick = function(){ clearInterval(timer); myDiv.style.width = '0'; timer = setInterval(function(){ if(parseInt(myDiv.style.width) < 500){ myDiv.style.width = parseInt(myDiv.style.width) + 5 + 'px'; myDiv.innerHTML = parseInt(myDiv.style.width)/5 + '%'; }else{ clearInterval(timer); } },16); } </script> 复制代码 【2】setTimeout 复制代码 <div id="myDiv" style="background-color: lightblue;width: 0;height: 20px;line-height: 20px;">0%</div> <button id="btn">run</button> <script> var timer; btn.onclick = function(){ clearTimeout(timer); myDiv.style.width = '0'; timer = setTimeout(function fn(){ if(parseInt(myDiv.style.width) < 500){ myDiv.style.width = parseInt(myDiv.style.width) + 5 + 'px'; myDiv.innerHTML = parseInt(myDiv.style.width)/5 + '%'; timer = setTimeout(fn,16); }else{ clearTimeout(timer); } },16); } </script> 复制代码 【3】requestAnimationFrame 复制代码 <div id="myDiv" style="background-color: lightblue;width: 0;height: 20px;line-height: 20px;">0%</div> <button id="btn">run</button> <script> var timer; btn.onclick = function(){ myDiv.style.width = '0'; cancelAnimationFrame(timer); timer = requestAnimationFrame(function fn(){ if(parseInt(myDiv.style.width) < 500){ myDiv.style.width = parseInt(myDiv.style.width) + 5 + 'px'; myDiv.innerHTML = parseInt(myDiv.style.width)/5 + '%'; timer = requestAnimationFrame(fn); }else{ cancelAnimationFrame(timer); } }); } </script>

这里是我引用的另外一个地方的兼容性不怎么好的一个数字动态变化计时器。如下:

> > //数字动态变化功能 - 传入参数依次为 数字要变化的元素,最终显示数字,数字变化开始值,变化持续时间,小数点位数 function countUp(elem, endVal, startVal, duration, decimal) { var startTime = 0; var dec = Math.pow(10, decimal); var progress, value; function startCount(timestamp) { if (!startTime) { startTime = timestamp; } progress = timestamp - startTime; value = startVal + (endVal - startVal) * (progress / duration); value = (value > endVal) ? endVal: value; value = Math.floor(value * dec) / dec; elem.text(value.toFixed(decimal)); progress < duration && requestAnimationFrame(startCount); } requestAnimationFrame(startCount); } countUp($('#show_count'), $('#count_num').text(), 0, 1000, 0);
转载请注明原文地址: https://www.6miu.com/read-49342.html

最新回复(0)