FC2ブログ

jQueryで、異なる要素のアニメーションを順番に実行する

jQueryでアニメーションを実行する処理でいろいろとハマったので、
昨日と今日と2日がかりで調べたことをまとめる。

jQueryのEffects APIには、animateやslideUp/slideDownなど、durationを指定することでアニメーションを行うメソッドがいくつかある。
同一要素に対してアニメーションを実行すると、アニメーションが順番に実行される。
これは、jQueryが要素ごとにアニメーション処理用のキューを管理しているからで、キューに格納された処理は前の処理が終わらないと実行されない。

アニメーションをメソッドチェーンでつなぐ必要は無く、
$("#id1").fadeOut(500).fadeIn(500).hide(500).show(500)
  .fadeOut(500).fadeIn(500);
でも
$("#id1").fadeOut(500);
$("#id1").fadeIn(500);
$("#id1").hide(500);
$("#id1").show(500);
$("#id1").fadeOut(500);
$("#id1").fadeIn(500);
でも順番に実行される。

ただし、(少なくともjquery-1.4.2では)durationを指定しない処理はキューに格納されないようで、
$("#id1").fadeOut(500).fadeIn(500).hide().show(500)
  .fadeOut(500).fadeIn(500);
とすると hide() と fadeOut(500) が同時に実行されて期待した動きにならない。

さて、本題の「異なる要素のアニメーションを順番に実行する方法」。
要素が異なるとキューも異なるので、
for(var i=0;i<3;i++){
  $("#id"+(i+1)).fadeOut(500).fadeIn(500);
}
とすると、3つの要素が同時に点滅してしまう。

delay()メソッドを使用することで、3つの要素を順番に点滅させることができる。
<注意:delay()メソッドが使用できるのは version 1.4 以降のjQuery>
指定した数字(単位はミリ秒)だけキューの処理を遅延させることができるので、
var interval = 0;
for(var i=0;i<3;i++){
  $("#id"+(i+1)).delay(interval).fadeOut(500).fadeIn(500);
  interval += 1500;
}
とすればいい。
interval に追加する数字により、次の要素が処理するまでの間隔を制御できる。
上記は interval += 1500 なので、次の要素が点滅するまでの間隔は500ミリ秒となる。
<2010/8/1追記>
上記の方法では、要素の数が大きくなると点滅が等間隔にならない場合があります。
修正版を jQueryで、異なる要素のアニメーションを順番に実行する 改 に記述しています。
<追記ここまで>

delay()はあくまでもキューの実行を遅延するので、durationを指定しない処理には効果が無いことに注意する必要がある。
durationを指定しない処理や、アニメーション以外の処理を制御したい場合は、setTimeout等を使ってキューを自作するか、以下のようなプラグインを使用する。
指定した処理をキューに追加して後でまとめて実行する jQuery Delay プラグイン

せっかくなので、処理実行中はロックをかけてイベントを受け付けない処理を、キューを利用して作ってみた。
// lockflgは、既にグローバル変数として初期値falseで宣言されている。
if(lockflg){return false;}  // lockflg == true なら処理しない
lockflg = true;
var interval = 0;
for(var i=0;i<3;i++){
  $("#id"+(i+1)).delay(interval).fadeOut(500).fadeIn(500);
  interval += 1500;
}
$("#id3").fadeIn(1,function(){lockflg = false;});  // lockflgをfalseにするためのダミー処理
最後に処理される要素のキューの最後尾に、害の無いダミーのアニメーションを追加し、そのcallback関数でフラグをオフにする。
こういったダミー処理で行うやり方は推奨されないんだろうなぁ。

ダミーのアニメーションを使わない処理も作ってみた
if(lockflg){return false;}  
lockflg = true;
var interval = 0;
for(var i=0;i<3;i++){
  if(i==2){
    // 最後にlockflgをfalseにする
    $("#id"+(i+1)).delay(interval).fadeOut(500).fadeIn(500,function(){lockflg = false;});
  }else{
    $("#id"+(i+1)).delay(interval).fadeOut(500).fadeIn(500);
  }
  interval += 1500;
}
ダミーを使う場合に比べると、ループのたびに余計な判定が入るが、多分些細な負荷だろう。
スポンサーサイト



コメント

コメントの投稿

非公開コメント

プロフィール

himax64

Author: 南西
30代後半の無職です。
就活もせずダラダラ生きてます。
作ったもの

最新記事
人気記事
検索フォーム
カテゴリ
月別アーカイブ
最新コメント
最新トラックバック
RSSリンクの表示
QRコード
QRコード
カウンター