web-dev-qa-db-ja.com

setIntervalを使用しているときに、Chromeでタブを切り替えて戻ると、スライダーが異常に追いつきます

私のサイトにはjQueryスライダーがあり、次のスライドに進むコードはnextImageという関数にあります。私はsetIntervalを使用してタイマーで関数を実行しましたが、それはまさに私が望むことをします:タイマーでスライドを実行します。ただし、Chromeのサイトに移動して別のタブに切り替えて戻ると、スライダーは「追いつく」までスライドを連続的に移動します。誰もこれを修正する方法を知っていますか?以下は私のコードです。

setInterval(function() {
nextImage();
}, 8000);
45
Nathan Shubert

Chrome with Javascript?)でタブがフォーカスされているかどうかを検出する方法?

window.addEventListener('focus', function() {
    document.title = 'focused';
},false);

window.addEventListener('blur', function() {
    document.title = 'not focused';
},false);

あなたの状況に適用するには:

var autopager;
function startAutopager() {
    autopager = window.setInterval(nextImage, 8000);
}
function stopAutopager() {
    window.clearInterval(autopager);
}

window.addEventListener('focus', startAutopager);    
window.addEventListener('blur', stopAutopager);

Chromiumの最新バージョンには、これを信頼性の低いものにするバグまたは「機能」があり、ユーザーがウィンドウのどこかで少なくとも1回クリックする必要があることに注意してください。詳細については、上記のリンクされた質問を参照してください。

38
ninjagecko

ここに答えを投稿します: Chromeでタブが非アクティブなときにsetIntervalを機能させるにはどうすればよいですか?

これを行うだけです:

setInterval(function() {
    $("#your-image-container").stop(true,true);
    nextImage();

}, 1000);

非アクティブなブラウザタブは、setIntervalまたはsetTimeout関数の一部をバッファリングします。 stop(true、true)-すべてのバッファリングされたイベントを停止し、最後のアニメーションのみを即座に実行します。

Window.setTimeout()メソッドは、非アクティブなタブで1秒あたり1つだけのタイムアウトを送信するようにクランプするようになりました。さらに、ネストされたタイムアウトを、HTML5仕様で許可されている最小値である4ミリ秒にクランプするようになりました(クランプに使用した10ミリ秒ではなく)。

15
www

いくつかのアイデアが思い浮かびます:


アイデア#1

短いバーストがidempotentになるようにできます。たとえば、次のように言うことができます。

_function now() {
    return (new Date()).getTime();
}

var autopagerInterval = 8000;

function startAutopager() {
    var startImage = getCurrentImageNumber();
    var startTime = now();

    var autopager = setInterval(
        function() {
            var timeSinceStart = now() - startTime();
            var targetImage = getCurrentImageNumber + Math.ceil(timeSinceStart/autopagerInterval);
            if (getCurrentImageNumber() != targetImage)
                setImageNumber(targetImage);  // trigger animation, etc.
        },
        autopagerInterval
    );
    return autopager;
}
_

この方法では、関数が1000回実行されても、わずか数ミリ秒で実行され、1回だけアニメーション化されます。

note:ユーザーがページを離れて戻ってきた場合、スクロールされています。これはおそらく元のポスターが望んでいるものではないでしょうが、時々あなたが望むものであるので、私はこの解決策を残します。


アイデア#2

Dem等性を追加する別の方法(nextImage()関数を保持し、ページの下部にスクロールさせない)は、関数に1秒後に消えるmutexロックを設定することです(別のタイムアウトでクリアされます) )。したがって、たとえsetInterval関数が1000回呼び出されたとしても、最初のインスタンスのみが実行され、他のインスタンスは何もしません。

_var locked = false;
var autopager = window.setInterval(function(){
    if (!locked) {
        locked = true;
        window.setTimeout(function(){
            locked=false;
        }, 1000);
        nextImage();
    }
}, 8000);
_

編集:これは動作しない可能性があります、以下を参照してください


アイデア#3

私は次のテストを試しました:

_function f() {
    console.log((new Date()) + window.focus());
    window.setTimeout(f, 1000);
}
f();
_

関数が毎秒呼び出されていることを示しているようです。これは奇妙です...しかし、これはコールバックが呼び出されているが、ページレンダラーがページの更新を拒否していることを意味すると思いますタブがフォーカスされていない間は、グラフィカルな方法で、ユーザーが戻るまですべての操作を遅らせますが、操作は積み重ねられ続けます。

また、window.focus()関数は、ウィンドウにフォーカスがあるかどうかを示しません。それはウィンドウにフォーカスを与えるため、無関係です。

おそらく、これは次のとおりです。 タブがフォーカスされているかどうかを検出する方法Chrome with Javascript? -ウィンドウがフォーカスを失ったときに間隔を設定解除できます。 (ぼかし)、フォーカスが合ったらリセットします。

6
ninjagecko

あなたの関数nextImage()で何が起こっているのか正確にはわかりませんが、同様の問題がありました。私が作成したjQueryイメージスライダーでsetInterval()でanimate()を使用していましたが、別のタブに切り替えて戻ったときに同じことを経験していました。私の場合、animate()関数はキューに入れられていたので、ウィンドウがフォーカスを取り戻すと、スライダーはおかしくなります。これを修正するために、animate()関数のキューイングを停止しました。

これを行うにはいくつかの方法があります。最も簡単な方法は.stop()ですが、この問題とその修正方法はjQueryのドキュメントに記載されています。見出しの追加ノートの下にあるこのページを確認してください: http://api.jquery.com/animate/

1
000justin000

私は同様の問題に直面していました、どういうわけかこの下のコードは私のためにうまく機能します。

            var t1= window.setInterval('autoScroll()', 8000);

    window.addEventListener('focus', function() {
        focused = true;
        window.clearInterval(t1);
        t1 = window.setInterval('autoScroll()', 8000);
    },false);

    window.addEventListener('blur', function() {
        focused = false;
        window.clearInterval(t1);
    },false)



function autoScroll()

    {

        if ( running == true){
            if ( focused = true){
                forwardSlide();
            }


        }

        else {

            running = true;

        }



    }
0

Soh Tanakaの画像スライダーを使用している場合は、これを追加するだけでGoogleを解決できますChrome問題:

$(".image_reel").stop(true, true).fadeOut(300).animate({ left: -image_reelPosition}, 500 ).fadeIn(300);

.stop()関数に注意してください。フェードインとフェードアウトを無視します。それが私のバージョンで使用したものです

ありがとう

0
Nasir