jQuery の animate()
は Deferred オブジェクトを返すので、jQuery Deferred を使って対象の違うアニメーションを順番に実行 のように pipe()
を使って順番に実行したり、when()
で複数のアニメーションが終わるまで待ったり、柔軟なフロー制御ができます。一方、RaphaelJS の animate()
は Element
/Set
を返すので、そのままだと同様に扱うことができません。
そこで RaphaelJS の Element
/Set
に、jQuery の Deferred
オブジェクトを返す animate()
的なものを追加してみました。Element
/Set
の prototype
は、それぞれ Raphael.el
と Raphael.st
から参照できます。
Raphael.el.animateWithDeferred = Raphael.st.animateWithDeferred = function(params, ms, easing, callback) {
var dfd = $.Deferred();
this.animate(params, ms, easing, function() {
if (typeof callback === 'function') {
callback.apply(this, arguments);
}
dfd.resolve();
});
return dfd;
};
単純に callback をラップして Deferred#resolve()
を呼ぶ実装です。これですと、もともとの animate()
と違い、Animation
オブジェクトを引数にとることができません。Animation
オブジェクトにも対応したい場合は、以下のような感じにすると良いでしょう。
Raphael.el.animateWithDeferred = Raphael.st.animateWithDeferred = function(params, ms, easing, callback) {
var dfd = $.Deferred(),
isAnim = typeof params.anim === 'object',
originalCallback = isAnim ? params.anim[100].callback : callback,
callbackWithDeferred = function() {
if (typeof originalCallback === 'function') {
originalCallback.apply(this, arguments);
}
dfd.resolve();
};
if (isAnim) {
params.anim[100].callback = callbackWithDeferred;
this.animate(params);
} else {
this.animate(params, ms, easing, callbackWithDeferred);
}
return dfd;
};
ちなみに Animation
オブジェクトを Set#animate()
に渡すと、全ての子要素でアニメーションが終わるたびに callback が呼ばれてしまうのでので注意が必要です。