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"
)
のアニメーションを停止する時でも
キュー名を指定するようにした方が無難だと思います。