Adobe のイージングを作ってみた

2dd4d077.png 以前仕事でイージング関数を実装する機会があったのですが、こちらの記事の数式を実装したら全然イケてなかったので、今回自分でイージング関数を作る事にしました。

 リンク先の記事はヒューリスティックなアプローチで話を進めていたので、ここではもう少し後ろのロジックを固めて考えてみる事にいたします。

 ちなみにどうしてイケてないかというと、左のグラフを見てわかる通り(青がリンク先の数式、赤が今回の数式、イージングのパラメータは +100 としている)、リンク先の数式では全体の 10% の時間で 50% も移動してしまっています。ここが実装するととても不自然に感じるポイントです。


イージングとは何か

 イージングとは、アニメーションに付加する加速・減速の効果の事です。ここでは、数直線上の運動に対するイージングのみを取り扱います。

 ある点が数直線上を 0〜1 まで移動するとき、その変位が x(t) で表されるとします(これをここではイージング関数と呼びます)。もし等速直線運動なら、x(t) = t としてしまって構わないでしょう。でも、点が加速したり減速したりする場合は、この書き方では明らかに不足です。では、x(t) をどういう関数にすれば、自然な動きになるのでしょうか。


利用するモデル

 まず、イージングの程度(加速・減速・等速)は、パラメータ v によって制御されると考えます。v の範囲は -100〜+100 で、「負で加速、0 で等速、正で減速、絶対値は加減速の程度」という動きになります。別にパラメータは 2 つでもいいし、値の範囲もこれに限らないのですが、ユーザの利便性を考慮して、今回はこのようにパラメータを選んでいます。

 次に、イージングを制御するパラメータ v の意味を考えてみます。おそらく、v は加速度に対応していると考えるのが最も自然なのではないでしょうか。そこで、ここでは加速度 a が一定で、それがパラメータ v によって制御されるようなモデルを考えてみます。


制約条件

 イージング関数を求める前に、制約条件を考えてみます。イージングの要件は、

  A) 始点と終点が一定であること
  B) 途中で折り返さない事

の 2 つです。これに、先ほどのモデルの

  C) 加速度が一定であること

を追加します。

 つぎに、それぞれ要件を定式化します。ここで、始点が 0、終点が 1 としてしまって一般性を失いません。したがって、各要件は次のように定式化されます。

  x''(t) = a …(1)
  x(0) = 0 …(2)
  x(1) = 1 …(3)
  x'(t) >= 0 …(4)

 ここで、t は時刻、x(t) はその時刻での位置です。本当は a は v に依存するので、a(v) と書くべきですが、ここでは式が煩雑にならないよう省略しています。

 A)が(2)(3)に、B)が(4)に、C)が(1)に対応しています。この式を微分方程式と見なして解くと、

  x(t) = t - (a/2)*(1-t)*t …(5)
  -2 <= a <= +2 …(6)

となります。


パラメータの対応付け

 ここで、v と加速度 a のスケールが異なっているので、対応付けを行います。-100 で最も程度の高い加速ですから、a の上限の +2 を割り当てます。また、+100 で最も程度の高い減速ですから、a の下限の -2 を割り当てます。すると、

  a(v) = -v/50

となります。これを(5)(6)に代入してみましょう。

  x(t,v) = t + (v/100)*(1-t)*t
  -100 <= v <= +100

これが、自然なイージング関数です。


実装における注意

 今回の関数は、0 <= t <= 1、0 <= x <= 1 という条件を暗黙に仮定して話を進めているので、実装するときにはスケールを一致させなくてはなりません。これについては、後ほどソースコードを載せようと思います。