丁度、jQueryで自動的にスライドさせて画像が切り替わり、ボタンをクリックすると次の画像・前の画像にスライドするイメージスライダーを自作してたんですが、ちょっと変な挙動が発生しました。
その挙動というのが、ボタンがフェードアウトとフェードインが繰り返されている感じです。これは自動的にスライドさせて最後の画像が標示された時は「NEXT」というボタンを非表示にして最初の画像の時は「PREV」ボタンを非表示にするアニメーションをチェックする関数を作って自動的にチェックしていました。もちろん自動的なアニメーションはJavaScriptのsetIntervalで実行しています。
で、それがどういう時に発生しているかというと、setintervalが実行されているときに、そのページを開いたまま、ほかのタブをしばらく見ていて、再度setintervalを使用しているタブに戻った時に発生している様です!!
原因と対策
さて、原因は恐らくsetIntervalを実行させているタブから別のタブを見ている間も、setIntervalで実行している関数が裏で実行されずにキューとして溜まっていて、再度タブを見た際に溜まっていた関数が一気に実行されるから、挙動が変なアニメーションになっているようでした。
で、解決策としては別のタブを選択したときに、clearIntervalを実行してsetIntervalを止めればいいと思ったので試した。
ウィンドウのフォーカスをチェックする
解決策として別のタブを選択しているかどうかを確認するにはウィンドウがアクティブ・非アクティブかをチェックすればいいので、フォーカスイベントをwindowオブジェクトに設定する。
focus | ページや対象の要素にフォーカスが当たった時に発生 |
---|---|
blur | ページや対象の要素からフォーカスが外れた時に発生 |
この関数を使って処理していきます。
最初にウィンドウにフォーカスを当てておく
まずこのページを開いた時にフォーカスを当てておきたいので下記のfocusを実行しておきます。
ちなみに、jQueryとJavaScript両方に同じfocusイベントがあります。
//jQuery
$(window).focus();
//JavaScript
window.focus();
タブが切り変わった時にフォーカスイベントを設定する
最初の処理はあくまで、ページを開いた時にフォーカスを当てたに過ぎないので、今度はタブが別のタブに移動したり(フォーカスが外れる)、元のタブに戻ってきた時(フォーカスが当たる)のイベントを検知して処理をします。
その時にsetIntervalでタイマーを設定したりclearIntervalでタイマーを解除すればいいわけです。
今回は、jQueryのbindメソッドでフォーカスイベントを検知したらコールバック関数でタイマーを処理します。
$(window).bind("focus",function(){ //フォーカスが当たったらタイマーを設定
timer=setInterval(animeFunc,1000);
}).bind("blur",function(){ //フォーカスが外れたらタイマーを解除
clearInterval(timer);
});
function animeFunc(){
//処理したい内容
}
下記にサンプルを作りました。
フォーカスが当たってる時は、数字をカウントアップしてボックスをアニメーションさせていますが、フォーカスが外れるとclearIntervalが実行されてタイマーが解除されるので、カウントアップとボックスのアニメーションが止まります。
また、フォーカスが当たるとsetIntervalでタイマーが設定され、カウントアップとボックスのアニメーションが実行されます。
フォーカスイベントに関数説明は下記が参考になります。