決まった動きをリズミカルにリピートしたい場合、マーカーを活用して効率を上げてみましょう。
目的を整理する
まず条件として、あるオブジェクトを点滅させるケースで模索していきます。
- キーフレームをあらかじめセッティングする
- マーカーのタイミングで動きを「再生」する
- 任意のタイミングでポンポンとマーカーを追加して使う
- セットした動きによってはタイミングを数フレームずらしたい
まずはリピートのためのアニメーションを想定して、キーフレームをセッティングします。これをマーカーのタイミングで再生するイメージです。
不透明度に直接打っても良さそうですが、何回も再利用するアニメーションの1セットと考えると、スライダー制御で準備しておくと都合が良さそうです。
エクスプレッションに変換していく
条件が整理できたので、エクスプレッション化していきましょう。
コントローラーの準備
まずマーカーに反応するための仕掛けとして、今何個目のマーカーかを検知するだけのスライダー制御を追加し準備しておきます。「[E]markerNum」とリネームしておきましょう。
マーカーを通り過ぎるたびに数値が増えるようにして使います。これにはこのあとエクスプレッションを仕込みます。
さらに該当のレイヤーにスライダー制御を追加し、「[E]動きをセット」とリネーム。
不透明度が数フレームで100→0となるアニメーションを想定し、これ用の2つのキーフレームをこのスライダー制御にセットしておきます。これは単純にキーフレームを打つだけ用です。
最後にもう一つスライダー制御を追加し「[E]marker判定nフレームズラし」にリネームします。
これはセットした動きによっては数フレームずらしたほうがタイミングよく見える場合に、一括で指定フレーム数だけアニメーションの再生タイミングをずらす機能として使います。
「[E]markerNum」用のエクスプレッション仕込み
解読に必要なグローバルオブジェクトはこちら。
marker.numKeys //このレイヤーにマーカーがいくつあるかカウント
marker.nearestKey(time) //現在の時間に一番近いマーカープロパティ
marker.nearestKey(time).index //現在の時間に一番近いマーカー番号
framesToTime() //フレームを時間に変換→30(フレーム)なら1(秒)になる
これで組み立てたのが下記です。
var reM=-effect("markerからズラす(f)")(1);//マーカーの何フレーム前から動かすか
var tugi=0;
if(marker.numKeys>0){
var nKey=marker.nearestKey(time);
if(time+framesToTime(reM) >= nKey.time){
tugi=nKey.index;
}else{
tugi=nKey.index-1;
}
}else{
value;
}
marker.numKeysでマーカーが打たれてなければvalueを使用する大枠の中に、本筋を組んであります。
nKeyに一番近いマーカーを代入しています。1秒と2秒にマーカーが打たれている場合、1.5秒までは1個目の、1.6秒以降が2個目のマーカー情報が入ってきます。.indexで何番目のマーカーという数値を取り出せます。
マーカーの中間で数値が更新されると使いづらいため、マーカーに辿り着いた瞬間に更新してほしいわけです。そのためtimeとnKey.timeを比べて、次のマーカーの時間になるまでは次のマーカー番号-1、次のマーカーに到達した段階でそのマーカー番号をtugiに代入します。
これでコントローラーが完成です。
不透明度用のエクスプレッション仕込み
仕上げに、これらコントローラーに反応する醍醐味エクスプレッションを不透明度に仕込んでいきましょう。
動き用のキーフレームやマーカーがないタイミングでエラーが出ないよう、if文で回避したら、メインのエクスプレッションは2行です。
nowframe=timeToFrames((time+inPoint)+framesToTime(reM))-timeToFrames(marker.key(fxNum).time);
fxSet.valueAtTime(framesToTime(nowframe));
nowframeでレイヤーのinPointからの時間と、アニメーションをマーカーから何フレームずらすかの「[E]marker判定nフレームズラし」の数値から、マーカーの時間を比べて現在のフレームを検知。
最後にfxSet.valueAtTime(framesToTime(nowframe));で「[E]動きをセット」のキーフレームを再生させます。
完成
これを繋いでエクスプレッション完成です。
reM=-effect("[E]marker判定nフレームズラし")(1);//マーカーの何フレーム前から動かすか
fxSet=effect("[E]動きをセット")(1);
fxNum=effect("[E]markerNum")(1);
if((fxSet.numKeys>0)&&(time>=0)&&(fxNum>0)&&(marker.numKeys>0)){
nowframe=timeToFrames((time+inPoint)+framesToTime(reM))-timeToFrames(marker.key(fxNum).time);
fxSet.valueAtTime(framesToTime(nowframe));
}else{
value;
}
後は同じコンポジションに曲などを配置し、再生しながらテンキーの「*」をポンポンと押すことでマーカーを連続で打てるので、リズムに乗せてレイヤーが点滅する動きが実現できます。
spaceで再生すると大抵fpsが落ちるため、テンキーの「.」で再生することで画面更新なしに音だけ再生できるので、まず処理落ちせずリズミカルにマーカーを打てます。
応用
不透明度や角度など1次元のプロパティなら上記でOKで、スケールなど2次元のプロパティ用にはエラーが出るので少し加筆します。
6行目のところです。
val=fxSet.valueAtTime(framesToTime(nowframe));
[val,val];
渡す数値を2次元にするため[]内に数値を2つ入れてやればOKです。記入が楽なようにvalなど短い変数を使いました。
↓一応コピペ用に全部置いておきます。
reM=-effect("[E]marker判定nフレームズラし")(1);//マーカーの何フレーム前から動かすか
fxSet=effect("[E]動きをセット")(1);
fxNum=effect("[E]markerNum")(1);
if((fxSet.numKeys>0)&&(time>=0)&&(fxNum>0)&&(marker.numKeys>0)){
nowframe=timeToFrames((time+inPoint)+framesToTime(reM))-timeToFrames(marker.key(fxNum).time);
val=fxSet.valueAtTime(framesToTime(nowframe));
[val,val];
}else{
value;
}
この記事へのコメントはありません。