こんにちわ!
3D・映像編集者 & オンライン講師のデリュージョン飯塚と申します!
本日はバウンスのエクスプレッションについて解説します!
- バウンス全体
 - value
 - numKeys
 - nearestKey
 - index
 - velocityAtTime
 - Math.sin
 - ...etc
 
この記事で学べるエクスプレッション
※一部抜粋
 
それではいきます。
目次
コード
freq = 5;
decay = 7;
n = 0;
if (numKeys > 0){
n = nearestKey(time).index;
if (key(n).time > time){
n--;
}
}
if (n == 0){
t = 0;
}else{
t = time - key(n).time;
}
if (n > 0){
v = velocityAtTime(key(n).time - thisComp.frameDuration/10);
value + v*amp*Math.sin(freq*t*2*Math.PI)/Math.exp(decay*t);
}else{
value;
}
使い方
キーフレームがあるパラメータにエクスプレッションを入力
※イージングをかけるとうまくいかないのでリニアにしましょう
 
 
例としてスケールが大きくなる円にバウンスをかけてみましょう
 
スケールのキーフレームはこんな感じ
 
エクスプレッションが無い状態の動き
 
スケールにエクスプレッションを追加するとこんな感じに
動きがポップになり使い勝手が良さそう
 
次はバウンスの動きの変え方を教えます
先程の式に
amp = 0.1;
freq = 5;
decay = 7;
という部分があったと思います
 
こちらの数値をいじればバウンスの動きが変わります
- amp = 振幅
 - freq = 振動数
 - decay = 減衰までの時間調整変数
 
名称は今僕が決めました
値を変えて動きの変化を見てみてください
のちほど式の原理を解説します!
エクスプレッションの勉強方法
ネットで調べてもたくさん出てきますが、まずは書籍での勉強をおすすめします。
冒頭でもちらっと書きましたが、上記の書籍が非常におすすめですね!
会話形式でかなりわかりやすかった!
飯塚式の意味を解説(知りたい人だけ!)
ここから先は知りたい人だけどうぞ!
飯塚全体の概要
まずはざっくりと式の中身を見ていきます
amp = 0.1;
freq = 5;
decay = 7;
これは後式の変数を決める部分
その後、エクスプレッションは2つのブロックに分けて見ることができます

①・・・nとtを定義するブロック
②・・・バウンスの実行ブロック
 
 
n ?? t ??
となるかもしれませんがnとtは②でバウンスを実行するために必要な変数なのです
②の式を見てみるとnとtが使われてますよね
 
 
とりあえず大まかにこのプログラムを説明すると
①でnとtを定義し、②でnとtを使いバウンスを実行している
になります
 
それではそれぞれ見ていきましょう
① nとtを定義

①ではnとtを定義していると解説しました
どのように定義しているのでしょうか?
例として、スケールにキーフレームを2つ打った場合を想定します
(2秒でスケール100、5秒でスケール200とする)
 
結論から書くと、nとtは以下のように定義されます

n = 0 (time < 2)
n = 1 (2 < time < 5)
n = 2 (5 < time)
t = 0 (time < 2)
t = 0→3 (2 < time < 5)
t = 0から上昇 (5 < time)
ではなぜそうなるのか
1行1行見ていきます
 
まずnは0と定義
 
n = nearestKey(time).index;
もしもキーフレームの数(numKeys)が0以上ならば以下を実行
nは現時間の1番近いキーフレーム(nearestKey(time))のインデックス番号の値(.index)になる
 
1個目のキーフレームならインデックス番号は1になるし、10個目ならそれは10です
今回キーフレームは2秒と5秒に打っています
例えば、現時間が1.3秒なら1番近いのは1個目のキーフレームなので
n = 1
例えば、現時間が3.8秒なら1番近いのは2個目のキーフレームなので
n = 2
 
現時点でのnの値はこのようになります
 
if (key(n).time > time){
n--;
}
現時間よりもn番目のキーフレーム時間のほうが大きかったら、nにマイナス1
 
例えば、現時間が1.3秒ならn = 1
現時間よりもn個目のキーフレーム時間(2秒)のほうが大きいので
n = 1 - 1
= 0
例えば、現時間が3.8秒ならn = 2
現時間よりもn個目のキーフレーム時間(5秒)のほうが大きいので
n = 2 - 1
= 1
例えば、現時間が5.6秒ならn = 2
現時間よりもn個目のキーフレーム時間(5秒)のほうが小さいので
n =2 のまま
 
よってnは時間によってこのように変化します
 
 
}
if (n == 0){
t = 0;
}else{
t = time - key(n).time;
}
次はtです
nが0ならtも0
nが0じゃないなら、tは現時間からn個目のキーフレーム時間を引いた値になります
 
例えば、現時間が3.8秒なら先程の説明よりn = 1
よってtは
t = 3.8 - 2(1個目のキーフレーム時間)
= 1.8
 
つまりtは時間によって変化する値です
キーフレームに位置ではt =0になりそこから時間と共に上昇する感じですね
 
まとめるとこうなるわけです
② バウンスの実行
①が理解できれば②は非常に簡単
 
if (n > 0){
v = velocityAtTime(key(n).time - thisComp.frameDuration/10);
nが0より大きいなら以下を実行
v = n番目のキーフレーム時間(key(n).time)のちょこっと前の時間(- thisComp.frameDuration/10)の速度
速度は今回でいうとスケールの上昇の速さになります
ややこしいですね でもnは今の例では1と2しかないので簡単です
 
例えば、n = 1の時のvは0になります
なぜかと言うと、1番目のキーフレーム時間(2秒)のちょこっと前の時間(1.98秒とかにしましょう)ではスケールは全く変わっておらず、速度は0だからです
 
n = 2の時のvは値を持ちます
2番目のキーフレーム時間(5秒)のちょこっと前の時間(4.98秒とかにしましょう)ではスケールはまさに大きくなっている最中で速度を持つからです
 
今回はn = 2の時にvは正の値を持ちます
(スケールが減少していればvは負の値になる 今回は正)
 
 
value + v*amp*Math.sin(freq*t*2*Math.PI)/Math.exp(decay*t);
}
value(その時間のスケールの値)にsin関数を自然対数eのべき乗で割ったものを足します
 
 
v*amp*Math.sin(freq*t*2*Math.PI)/Math.exp(decay*t)
この部分は数学の話になってしまうので詳しくは解説しませんが
最初は値が振動するけどtが増加するにつれて0に収束していくよと言う感じです
 
ここでamp、freq、decayが使われていますね
 
ampを変えれば振幅が変わりそうだし
decayを変えれば収束までの時間が変わりそうでしょう?
この辺は数学の知識なので説明は省きますがなんとなく想像はつくと思います
 
 
さて、vはn = 2の時に値をもちますので
つまりは2番目のキーフレームからvalueの値に関数が足されバウンスの表現を実現できるわけです
else{
value;
}
elseは冒頭のif (numKeys > 0){ にかかってきます
今までの話はすべてキーフレームが存在したらの話でした
つまりはキーフレームがないなら特に何もしないよと
まとめ
- バウンスのコードを解説
 - バウンスは有能なので使おう
 - 式の意味もできれば理解しよう
 
それでは今回の記事は以上です!
デリュージョン飯塚でした。
2025年11月4日 追記
ここまで読んでいただいたお礼として、本ブログのオンラインショップ(講座)で使える
特別クーポンをお贈りいたします。
クーポンコード:blog10off
割引率:10%OFF
以下のショップで使う事が可能です。
»IzukaEffects-Online
クーポンは数量限定(5個)です。
先着人数に達した場合、「クーポンは有効ではありません」と表示されますのでご注意ください。
TurbulenceFD、World Creatorは提携商品のため使用不可となっています。
※当サイトは、広告主から支払われる広告収入を主な収入源として運営を行っています。
※当サイトの記事では、商品・サービスの紹介に広告主のアフィリエイト広告を利用しています。
※記事で紹介した商品・サービスを購入すると、広告主から当サイトに報酬が支払われることがあります。
インターネット上の広告表示(消費者庁)
インターネット広告倫理綱領及び掲載基準ガイドライン
				IzukaEffects	

