How can I make setInterval also work when a tab is inactive in Chrome?

后端 未结 13 2157
被撕碎了的回忆
被撕碎了的回忆 2020-11-21 09:59

I have a setInterval running a piece of code 30 times a second. This works great, however when I select another tab (so that the tab with my code becomes inacti

13条回答
  •  谎友^
    谎友^ (楼主)
    2020-11-21 10:28

    On most browsers inactive tabs have low priority execution and this can affect JavaScript timers.

    If the values of your transition were calculated using real time elapsed between frames instead fixed increments on each interval, you not only workaround this issue but also can achieve a smother animation by using requestAnimationFrame as it can get up to 60fps if the processor isn't very busy.

    Here's a vanilla JavaScript example of an animated property transition using requestAnimationFrame:

    var target = document.querySelector('div#target')
    var startedAt, duration = 3000
    var domain = [-100, window.innerWidth]
    var range = domain[1] - domain[0]
    
    function start() {
      startedAt = Date.now()
      updateTarget(0)
      requestAnimationFrame(update)
    }
    
    function update() {
      let elapsedTime = Date.now() - startedAt
    
      // playback is a value between 0 and 1
      // being 0 the start of the animation and 1 its end
      let playback = elapsedTime / duration
    
      updateTarget(playback)
      
      if (playback > 0 && playback < 1) {
      	// Queue the next frame
      	requestAnimationFrame(update)
      } else {
      	// Wait for a while and restart the animation
      	setTimeout(start, duration/10)
      }
    }
    
    function updateTarget(playback) {
      // Uncomment the line below to reverse the animation
      // playback = 1 - playback
    
      // Update the target properties based on the playback position
      let position = domain[0] + (playback * range)
      target.style.left = position + 'px'
      target.style.top = position + 'px'
      target.style.transform = 'scale(' + playback * 3 + ')'
    }
    
    start()
    body {
      overflow: hidden;
    }
    
    div {
        position: absolute;
        white-space: nowrap;
    }
    ...HERE WE GO


    For Background Tasks (non-UI related)

    @UpTheCreek comment:

    Fine for presentation issues, but still there are some things that you need to keep running.

    If you have background tasks that needs to be precisely executed at given intervals, you can use HTML5 Web Workers. Take a look at Möhre's answer below for more details...

    CSS vs JS "animations"

    This problem and many others could be avoided by using CSS transitions/animations instead of JavaScript based animations which adds a considerable overhead. I'd recommend this jQuery plugin that let's you take benefit from CSS transitions just like the animate() methods.

提交回复
热议问题