修正:
jQueryアニメーションのところ、わざわざreturn d.promise()でなくてもanimate()はpromise()を返すのでそのままreturnでよかったです。
CSSアニメーションやjQueryアニメーション、さらにそれ以外の様々な動作を順番に実行するような処理を実装したいと思い、Deferredによる実装方法を試してみました。
ADs
順番に動作させるためには「処理が完了した」ということを判定しないといけません。
CSSアニメーションは完了時にtransitionendというイベントが発火します。
※keyframeアニメーションの場合はanimationendというイベントになります。
このイベントに対してresolve()をバインドさせれば、Deferredにより連鎖的な処理を実装できそうです。
jQueryアニメーションだけの場合はDeferredを使うことで簡単に実装できます。
過去記事もご参照ください(と言っても当時は思い切り間違ってたのでだいぶ恥ずかしい…)
Ajaxじゃなくても使える、$.Deferredで好きな処理を連鎖的に実行する方法
スターフィールド様のこちらの記事のほうがわかりやすいですね(;´∀`)
jQuery.Deferredでわかりやすく順番にアニメーションする方法
TransitionEndイベントはCSSアニメーション終了時に発火します(実装時にはベンダープレフィックスが必要です)。
このイベントにresolve()をバインドすることで、CSSアニメーション終了を伝達します。
1 2 3 4 5 6 7 8 9 10 11 |
var anim1 = function(){ var d = new $.Deferred; $('.block').css({ left: '+=300px', transition: '1s' }).on('webkitTransitionEnd',function(){ //ここでCSSアニメーションが終了している d.resolve(); }); return d.promise(); } |
これでthen()やwhen()など、jQuery.Deferredに関連する関数を使った処理が構築できます。
CSSアニメーションと同じようなかたちで、アニメーション完了時にresolve()をバインドします。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
var anim3 = function(){ /* animate()はpromise()を返すのでそのままreturnでよかった…。 var d = new $.Deferred; $('.block').animate({ left: '-=200px', transition: '0s' },'1000','linear').promise().done(function(){ //ここでjQueryアニメーションが終了している d.resolve(); }); return d.promise(); */ /* 以下でよい */ return $('.block').animate({ left: '-=200px', transition: '0s' },'1000','linear'); } |
デモでは
1.CSSアニメーションで右に300px移動
2.CSSアニメーションで下に100px移動
3.jQueryアニメーションで左に200px移動
4.1秒静止し、色を#00fに変える。
5.CSSアニメーションで下に100px移動
という処理を順番に行っています。
アニメーション以外にsetTimeoutによる遅延処理(非同期なのでDeferredを使わないと次の処理が実行されてしまう)も加えました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 |
(function($){ //CSSアニメーション var anim1 = function(){ var d = new $.Deferred; $('.block').css({ left: '+=300px', transition: '1s' }).on('webkitTransitionEnd',function(){ d.resolve(); }); return d.promise(); } //CSSアニメーション var anim2 = function(){ var d = new $.Deferred; $('.block').css({ top: '+=100px', transition: '0.5s' }).on('webkitTransitionEnd',function(){ d.resolve(); }); return d.promise(); } //jQueryアニメーション /* animate()はpromise()を返すのでそのままreturnでよかった var anim3 = function(){ var d = new $.Deferred; $('.block').animate({ left: '-=200px', transition: '0s' },'1000','linear').promise().done(function(){ d.resolve(); }); return d.promise(); } */ var anim3 = function(){ return $('.block').animate({ left: '-=200px', transition: '0s' },'1000','linear'); } //setTimeoutによる遅延 var anim4 = function(){ var d = new $.Deferred; setTimeout(function(){ $('.block').css({ background: '#00f' }); d.resolve(); },1000); return d.promise(); } //CSSアニメーション var anim5 = function(){ var d = new $.Deferred; $('.block').css({ top: '+=100px', transition: '2s' }).on('webkitTransitionEnd',function(){ d.resolve(); }); return d.promise(); } //実行 $(window).on('load',function(){ anim1().then(anim2).then(anim3).then(anim4).then(anim5); }); })(jQuery); |
デモのようなアニメーションの構築はもちろんですが、たとえば
CSSによるローディング → Ajaxで外部データ取得 → jQueryアニメーションを伴って表示させる
といった感じで使えたらいいな、と思います。
ADs
コメントはまだありません。