jQuery で複数の要素のアニメーションが全て終わったら何かを実行する

jQuery でたくさんの要素をグリグリ動かしたいときに、完了時刻の違う複数の要素のアニメーションが両方終わった時に何かを実行する、というような処理をしたいと思うことがある。

完了時刻が遅い方のコールバックに処理を書けば、望みのことは出来る。ただ、このようにして書かれたコードは変更に弱いし、見ただけで何をしたいコードなのかがパッと見わからなくなる。

アニメーション完了後に何かをするといえば、慣例的に以下のように書くことがポピュラーである。

$('.target')
    .animate({
        top: '+=100px'
    }, 500, 'swing', function () {
        // アニメーション完了後に実行される
        alert('done!');
    });

jQuery 1.6 から、 animatefadeOut といった処理がキューに入る系のメソッドでは、キューがすべて空っぽになった時点で promise されていれば、 resolve が発動するようになっている。*1

とすると上コードは、以下のようにもかける。

$('.target')
    .animate({
        top: '+=100px'
    }, 500, 'swing')
    .promise().done(function () {
        // アニメーション完了後に実行される
        alert('done!');
    });

そして嬉しいことに、 promise する jQuery オブジェクトは、複数の要素が選択されていた場合、選択されているすべての要素のキューが消化されたタイミングで resolve が発動するみたい。

素直に jQuery の恩恵を受けておきましょう。

*1:こんな説明でいいのか……? このあたりの詳しい説明は他のリソースにお任せすることにする。