animate() の queue オプションで複数のアニメーションを平行して実行する方法

1.7 から .animate() のオプション queue を指定することで 複数のキューにアニメーションを格納できるようになりました。 異なるキューのアニメーションは それぞれ平行して実行させることができるので、 より複雑にアニメーションさせることができるようになります。 (同じプロパティを異なるキューで同時にアニメーションさせる ことは今のところ無理なようです)

主に jQuery 2.0.3 を使って調べたので、他のバージョンでは 当てはまらないことがあるかもしれませんのでご注意下さい。

別のキューでアニメーションを動かすには

別のキューにアニメーションを格納するには .animate()に渡すオプション queue に デフォルト以外のキューの名前を指定します。 デフォルトのキュー名は"fx"なので それ以外の名前を付けるようにします。

// プロパティ top を30px増加するアニメーションを
// デフォルト以外のキューで実行する
// options は .animate() に渡すオプションオブジェクト
options.queue = "キュー名"; // "fx"以外の名前を付ける
// target はアニメーションさせる要素を持つ jQuery オブジェクト
target.animate( { top: "+=30px" }, options );

デフォルトのキューと異なり、 .animate() しただけでは アニメーションが開始しません(queue()だけされて dequeue()されない)。 キューに格納されている次のアニメーションは デフォルトキューの時と同じく自動で実行されるのですが、 キューのアニメーションを最初に開始する時だけは 手動で始める必要があります。 キューされたアニメーションを開始するには dequeue()を実行します。

// キュー名を指定して dequeue する
target.dequeue("キュー名");

すでにそのキューでアニメーションが実行中の場合は dequeue()を実行する必要はありません。 そのキューのアニメーションの実行中に dequeue()を実行してしまうと 一つのキューで複数のアニメーションが実行されてしまいます。 そのようなことを防ぐために あらかじめそのキューでアニメーションが実行中か確認してから dequeue()を実行するようにします。

例えば以下のように、そのキューでアニメーションが実行されて いるかどうかを返す関数を定義しておき、

// 指定した要素とキューでアニメーション中か否かを返す
function isAnimating(elem, queue){
  queue = queue || "fx";

  return jQuery.grep(jQuery.timers, function( timer ){
    return elem === timer.elem && queue === timer.queue;
  }).length > 0;
}
// ※この関数では .delay() による停止中か否かまでは
//   判断できません

そして、.animate()の実行前に 対象要素がそのキューでアニメーション中かどうかを調べて dequeue()するかどうか判断します。

// elem は対象要素
options.queue = "キュー名";
if( isAnimating(elem, "キュー名") ){
  $(elem).animate(properties, options);
} else {
  $(elem).animate(properties, options);
  jQuery.dequeue(elem, "キュー名");
}
リストに戻る

注意点:.stop()する時はキュー名を省略せずに指定する

デフォルト以外のキューでアニメーションしている場合は .stop() にキュー名を指定するようにした方が無難です。 (これ以降はその理由です)

.stop()の用法は stop(type, clearQueue, gotoEnd)で、 それぞれ キュー名(文字列)、キューを空にするかどうか(真偽値)、 要素を目的値に移動するかどうか(真偽値)、です。

// 使用例:キュー名のキューの現在実行中のアニメーションを
// 目的値に移動して停止しキューを空にする
target.stop("キュー名", true, true);

キュー名を省略した時は その要素の全てのキューのアニメーションが停止します。 しかし、キュー名を省略し 且つ キューを空にしようとした場合、

// キュー名を省略し 且つ キューを空にする場合
target.stop(true);
// または target.stop(true, true)

全てのキューのアニメーションが停止するのに対して 空になるのはデフォルトキューだけで、 他のキューは空になりません。

また、キュー名を省略し 且つ 目的値に移動させる場合、

// キュー名を省略し 且つ 目的値に移動させる場合
target.stop(true);
// または target.stop(false, false) など

こちらも全てのキューのアニメーションが停止するのに、 停止後次のアニメーションが実行されるのは (dequeue()するのは)デフォルトキューだけになります。

キューを空にするメソッド .clearQueue() でキュー名を省略した場合はデフォルトキューを空にするので、 .stop()のキュー操作に関しては矛盾が無いと思います。 おそらく、キュー名を省略した時 デフォルトキューだけではなく 全てのキューのアニメーションを停止してしまうのが おかしいのだと思います。 (デフォルトキューだけを停止するようにすれば 停止後の次アニメーションの実行の矛盾も解消されます)

そういうわけで、デフォルト以外のキューでアニメーションを 実行していて.stop()を使う場合は、 デフォルトキュー(キュー名は"fx") のアニメーションを停止する時でも キュー名を指定するようにした方が無難だと思います。

リストに戻る

スポンサードリンク