setTimeout,setInterval,requestAnimationFrame动画精确度对比
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <style> .progress { width: 0; height: 20px; line-height: 20px; background: yellowgreen; } </style> </head> <body> <div id="bar" class="progress">0%</div> <button id="btn">setTimeout</button> <button id="btn1">setInterval</button> <button id="btn2">requestAnimationFrame</button> <script> // 使用setTimeout,第一次执行完定时回调,全部执行完调用clearTimeout清除定时器 btn.onclick = function(){ console.time('setTimeout') var progress = 0 var timer = setTimeout(function fn() { progress ++ if(progress <= 100){ bar.style.width = progress + 'px' bar.innerHTML = progress + '%' timer = setTimeout(fn, 1000/60) }else{ console.timeEnd('setTimeout') clearTimeout(timer) } }, 1000/60) } // 使用setInterval,全部执行完调用clearInterval清除定时器 btn1.onclick = function(){ console.time('setInterval') var progress = 0 var timer = setInterval(function fn() { progress ++ if(progress <= 100){ bar.style.width = progress + 'px' bar.innerHTML = progress + '%' }else{ console.timeEnd('setInterval') clearInterval(timer) } }, 1000/60) } // 使用requestAnimationFrame,用法与settimeout相似 // 第一次执行完调用requestAnimationFrame,但不需要设置时间,全部执行完调用cancelAnimationFrame btn2.onclick = function(){ console.time('requestAnimationFrame') var progress = 0 var timer = requestAnimationFrame(function fn(){ progress ++ if(progress <= 100){ bar.style.width = progress + 'px' bar.innerHTML = progress + '%' timer = requestAnimationFrame(fn) }else{ console.timeEnd('requestAnimationFrame') cancelAnimationFrame(timer) } }) } // 理论动画时长约1666ms,setTimeout和setInterval设置60fps,requestAnimationFrame默认 // setTimeout: 1700.072021484375ms // setInterval: 1617.007080078125ms // requestAnimationFrame: 1664.283203125ms // 结论:setTimeout和setInterval动画执行误差约20%-30%,requestAnimationFrame误差约1% </script> </body> </html>