animate() の easing の定義方法

.animate()で指定する easing 関数は、 アニメーションの開始地点から目的地点までの進み方を定義します。 指定方法は こちら に記録したので、ここでは独自に easing 関数を 定義する方法とその注意点を記録しようと思います。

主に jQuery 1.9.1 を使って調べたので、他のバージョンでは 当てはまらないことがあるかもしれませんのでご注意下さい。 長い間変わっていないようですが、 たぶん公式にはドキュメント化されていません。 その点は留意して下さい。

easing 関数の定義方法

easing 関数は以下のように jQuery.easingオブジェクトに定義します。

// myEasing という名前の easing 関数を定義
$.easing["myEasing"] = function(p, t, s, e, d){
  // 数値を返す
};

// こっちでもよい
$.extend( $.easing, {
  myEasing: function(p, t, s, e, d){
    // 数値を返す
  }
});

この時、jQuery.easingオブジェクトの プロパティ名が easing 関数の名前になります。 .animate()で指定する時はこの名前を使います。

// 定義時のプロパティ名を指定する
$( element ).animate({ marginLeft:  "+=100px" }, 400, "myEasing");
// または
$( element ).animate({ marginLeft:  "+=100px" },
                     { easing: "myEasing" }   );
リストに戻る

easing 関数への引数

今のところ、easing 関数には5つの引数が渡されています。

p
アニメーションの進捗状況を表す 0 から 1 の間の数値。 0 が開始時点で 1 が終了時点。
t
アニメーション開始時から現在までの経過時間。ミリ秒単位。 1.8 から整数ではなくなった。
s
常に0
e
常に1
d
.animate()で指定した duration の値。
リストに戻る

easing 関数の返り値

アニメーションするプロパティの値は easing 関数の返り値をもとに決定されます。そのため、 easing 関数の返り値は数値になるようにします。 その返り値を使って、以下のような式で アニメーションするプロパティの値が決定されています。

now = ( end - start ) * eased + start;
// now   ... アニメーションするプロパティの値
// end   ... .animate() で指定したプロパティの目的値
// start ... アニメーション開始時のプロパティの値
// eased ... easing 関数の返り値

eased が0なら now は start になり、eased が1なら now は end になります。 つまり、easing 関数の返り値は、 アニメーション開始時のプロパティの値を0.animate()で指定したプロパティの値を 1とした場合の割合の値になります。 マイナスの値や1以上の値も返すことができます。

例えば、marginLeftプロパティを100から 200ピクセルにアニメーションする場合、 指定した easing 関数がある時点で0.5を返せば その時点でのプロパティの値は150になり、 他の時点で1.5を返せば250になり、 また別の時点で-1.5を返せば -50になります。

jQuery 1.7 まではアニメーションの完了時点で easing 関数が 目的値以外の値(つまり1以外の値)を 返してもプロパティの値に反映されず .animate()で指定した目的値が設定されますが、 1.8 以降では完了時点でも easing 関数の返り値が反映されるようになりました。

リストに戻る

step 関数や progress 関数との比較

同じようにアニメーションをカスタマイズできる .animate()のオプション、step と progress(1.8以降) との違いについて記録しておきます。

実行順序

easing 関数 → step 関数 → (プロパティ更新) → progress 関数という実行順序になります。そのため、 easing 関数での変更結果は step 関数や progress 関数で 変更することができます。

リストに戻る

プロパティごとに指定可能

easing 関数はプロパティごとに指定できます。step 関数と progress 関数は.animate()ごとにしか 指定できません。

リストに戻る

あらかじめjQuery.easingに登録する必要がある

step 関数や progress 関数は.animate()を呼ぶ時点で 関数オブジェクトを指定することができますが、 easing 関数の場合はあらかじめjQuery.easingに 登録しておいてから.animate()でその名前を 文字列で指定します。 また、jQuery.easingオブジェクトは全ての .animate()で共有します。
そのため、 「この.animate()の呼び出しだけにちょっとした 独自の easing 関数を作って使いたいな」 というような用途には不向きです。(※ easing 関数を関数オブジェクトで指定できるようになる プラグイン もあります)

// easing 
$( elem ).animate({ top: ["100px", "myEasing"] }); // 名前で指定

// step, progress
$( elem ).animate({ top: "100px" },
                  {
                    step: function( now, tween ){
                      // 関数オブジェクトで指定可能
                    },
                    progress: function( anim, percent, remaining ){
                      // 関数オブジェクトで指定可能
                    }
                  });
リストに戻る

実行中の情報は時間のみ

easing 関数は進捗状況(第1引数)と経過時間(第2引数)、 継続時間(duration、第5引数)は引数から知ることができますが、 移動距離(開始値や目的値)や対象要素、対象プロパティなどを 知ることができませんし、jQuery.easingに あらかじめ登録して.animate()で共用するため クロージャで情報を渡すにも向いていません。

一方、step 関数や progress 関数は それらの情報を取得でき、関数オブジェクトを指定するため クロージャで情報を追加することもできます。

// step, progress は様々な情報にアクセス可能
var info = { otherElem: $( otherElem ) };
$( elem ).animate({ top: "100px" },
                  {
                    step: function( now, tween ){
                      // this は 対象要素
                      // tween には様々な情報(プロパティ名,
                      // 開始値, 目的値, 単位 など)が入る
                      var elem = info.otherElem;
                    },
                    progress: function( anim, percent, remaining ){
                      // this は 対象要素
                      // anim には様々な情報(tweens プロパティから
                      // Tween オブジェクトを取得できる)が入る
                      var elem = info.otherElem;
                    }
                  });
リストに戻る

対象プロパティの値以外に干渉できない

上の通り取得できる情報は数値のみのため、 easing 関数の返り値でしかアニメーションに影響を 及ぼすことができません。つまり、対象プロパティの値にしか 干渉できません。step 関数や progress 関数は対象要素に アクセスできるので対象プロパティ以外のプロパティの値を 変更することができます。

リストに戻る

まとめ

easing 関数で 時間に対するプロパティの値を割合で返す以外のことを行うのは 難しいでしょう。 つまり、開始地点から目的地点までの進み方についての カスタマイズには適していますが、それ以上の アニメーションの細かい挙動をカスタマイズしたい場合は step 関数や progress 関数を利用するようにした方がいいと思います。

スポンサードリンク