Когда дело доходит до анимации, нам говорят, что setInterval
это плохая идея. Потому что, например, цикл будет выполняться независимо от того, что еще происходит, а не вежливо уступать, как requestAnimationFrame
воля. Также некоторые браузеры могут «играть в догонялки» с помощью цикла setInterval, где неактивная вкладка могла ставить в очередь итерации, а затем запускать их все очень быстро, чтобы наверстать упущенное, когда она снова станет активной.
Если вы хотите использовать setInterval
, но хотите вежливости исполнения requestAnimationFrame
, в Интернете есть несколько вариантов!
От Сергея Шиманского:
var requestInterval = function (fn, delay) ( var requestAnimFrame = (function () ( return window.requestAnimationFrame || function (callback, element) ( window.setTimeout(callback, 1000 / 60); ); ))(), start = new Date().getTime(), handle = (); function loop() ( handle.value = requestAnimFrame(loop); var current = new Date().getTime(), delta = current - start; if (delta >= delay) ( fn.call(); start = new Date().getTime(); ) ) handle.value = requestAnimFrame(loop); return handle; );
См. Комментарий о вариантах, таких как очистка интервала, а также установка и очистка тайм-аутов.
Это была вариация версии Джо Ламберта:
window.requestInterval = function(fn, delay) ( if( !window.requestAnimationFrame && !window.webkitRequestAnimationFrame && !(window.mozRequestAnimationFrame && window.mozCancelRequestAnimationFrame) && // Firefox 5 ships without cancel support !window.oRequestAnimationFrame && !window.msRequestAnimationFrame) return window.setInterval(fn, delay); var start = new Date().getTime(), handle = new Object(); function loop() ( var current = new Date().getTime(), delta = current - start; if(delta >= delay) ( fn.call(); start = new Date().getTime(); ) handle.value = requestAnimFrame(loop); ); handle.value = requestAnimFrame(loop); return handle; ) window.clearRequestInterval = function(handle) ( window.cancelAnimationFrame ? window.cancelAnimationFrame(handle.value) : window.webkitCancelAnimationFrame ? window.webkitCancelAnimationFrame(handle.value) : window.webkitCancelRequestAnimationFrame ? window.webkitCancelRequestAnimationFrame(handle.value) : /* Support for legacy API */ window.mozCancelRequestAnimationFrame ? window.mozCancelRequestAnimationFrame(handle.value) : window.oCancelRequestAnimationFrame ? window.oCancelRequestAnimationFrame(handle.value) : window.msCancelRequestAnimationFrame ? window.msCancelRequestAnimationFrame(handle.value) : clearInterval(handle); );
Отчасти это более подробно, потому что он обрабатывает префикс поставщика. Скорее всего, вам не нужен префикс производителя. См. Поддержку в браузере для requestAnimationFrame. Если вам нужна поддержка IE 9 или Android 4.2-4.3, вы не можете использовать это вообще. Префикс производителя помогает только в довольно старых версиях Safari и Firefox.
И еще один от StackExchange:
window.rInterval=function(callback,delay) ( var dateNow=Date.now, requestAnimation=window.requestAnimationFrame, start=dateNow(), stop, intervalFunc=function() ( dateNow()-start