1. ホーム
  2. ジャバスクリプト

[解決済み】Chromeでタブが非アクティブのときにもsetIntervalを動作させるにはどうすればいいですか?

2022-04-30 12:12:16

質問

私は setInterval が1秒間に30回実行されます。この機能は素晴らしいのですが、別のタブを選択すると(コードのあるタブが非アクティブになるように)、このタブの中の setInterval がなぜかアイドル状態になってしまいます。

こんな簡易テストケースを作ってみました( http://jsfiddle.net/7f6DX/3/ ):

var $div = $('div');
var a = 0;

setInterval(function() {
    a++;
    $div.css("left", a)
}, 1000 / 30);

このコードを実行してから他のタブに切り替え、数秒待ってから戻ると、アニメーションは他のタブに切り替えたときのポイントで継続されます。つまり、タブがアクティブでない場合に、アニメーションが1秒間に30回実行されるわけではありません。このことは setInterval 関数が1秒ごとに呼び出されます。タブがアクティブでない場合、これは30ではなく、1つか2つになります。

これは、パフォーマンスを向上させるための設計によるものだと思いますが、この動作を無効にする方法はあるのでしょうか?実際、私のシナリオでは不利になります。

解決方法は?

多くのブラウザでは、非アクティブなタブの実行優先度が低く、これがJavaScriptのタイマーに影響を与えることがあります。

トランジションの値が フレーム間の実経過時間 を使用すると、この問題を回避できるだけでなく、より滑らかなアニメーションを実現することができます。 requestAnimationFrame プロセッサがそれほど忙しくなければ、最大60fpsを実現することができるからです。

以下は、バニラJavaScriptの例です。 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;
}
<div id="target">...HERE WE GO</div>


バックグランドタスク用(UIに関係ないもの)

@UpTheCreek のコメントです。

<ブロッククオート

プレゼンテーションの問題では良いのですが、やはり 走り続けなければならないことがある。

バックグラウンドタスクがある場合 が必要です。 を指定された間隔で正確に実行させるために HTML5 ウェブワーカー . を見てみましょう。 以下、Möhreさんの回答 をご覧ください。

CSSとJSのアニメーション。

この問題と その他多数 は、かなりのオーバーヘッドを追加するJavaScriptベースのアニメーションの代わりに、CSSトランジション/アニメーションを使用することで回避することができます。私のおすすめは、次のような方法です。 jQueryプラグイン のようなCSS遷移を利用することができます。 animate() メソッドを使用します。