2012年1月13日金曜日

AE キーフレームのループあれこれ

キーフレームを1サイクル作ってそのアニメーションをループさせたい時、キーフレームをコピーするよりも、エクスプレッションの記述で簡単にできちゃいます。

loopIn(type = "cycle", numKeyframes = 0)
loopOut(type = "cycle", numKeyframes = 0)

上の文は、エクスプレッションを追加すると出てくる矢印ボタンから、メニューをたどると簡単に出せます。

矢印を押して出てくるメニュー、propertyの中にあります。

2タイプある文から、まず
loopIn(type = "cycle", numKeyframes = 0)
を適用してみた結果


グラフの実線が実際作ったキーフレームで、点線がエクスプレッションでループされているアニメーションです。
実際のキーフレームより前の時間だけループします。
お察しの通り、このloopInはあまり使う事はないでしょう・・


ちなみに、エクスプレッションの動きをグラフに点線で表示するにはココを押す





次が本命
loopOut(type = "cycle", numKeyframes = 0) 
結果は、


そうそうコレコレ。
ちなみに、前後にループを足すには少々ややこしい文が必要になりますので、特に理由がなければコンポジションの先頭でキーフレームを作って、このloopOutを使うと良いと思います。

loopIn loopOut の意味はそんなところです。
そして気になるのが()の中。type="cycle"とありますが、これはどのようにループするかというのを指定しています。

試しに「cycle」を「pingpong」と書き換えてみます。
loopOut(type = "pingpong", numKeyframes = 0) 
結果は、


いったりきたり、RAMプレビュー再生のオプションにもある、あの動きです。
んん、たまには使うかなぁ

次は、「cycle」を「offset」と書き換えてみます。

loopOut(type = "pingpong", numKeyframes = 0) 
結果は、


最初と最後のキーの値を差分して足したうえでループしてくれます。
階段をはずみながら落ちていくボール、など使うケースはそこそこあるかと思います。
このループ形式は、3Dソフトで歩行アニメーションの足の位置なんかで結構使ったりします。


次はとてもステキなループです。
とりあえず結果は、


タイムラインの最初に実際のキーフレームがあります。
そして、レイヤーにマーカーを付けて、コメントに数値を打ち込みます。
あら!マーカー位置から数値の回数分ループしてるじゃないですかっ!もちろんマーカーの位置を移すとアニメーションもついていきます。
マスクシェイプにも使えるので、キャラのまばたきなど利用するシチュエーションは無限大!
ちなみにキーフレームは実際のアニメーションに反映されませんので、 そこも動かしたい場合は1Fにマーカーを作りコメントを「1」とすると良いでしょう。

エクスプレッション文は

loopTime = 0;
numLoop = 0;
keyN = 0;
shiftTime=0; 
cycleTime =key(numKeys).time; 

if (marker.numKeys){
keyN = marker.nearestKey(time).index;
if (marker.key(keyN).time > time) keyN--;
}

if (keyN > 0) {
numLoop = parseInt(marker.key(keyN).comment);
shiftTime = time - marker.key(keyN).time;

if (shiftTime < numLoop * cycleTime ) {
loopTime = shiftTime % cycleTime ;
}
}

valueAtTime(loopTime )
 

これはとあるサイトから見つけてきた文で、ボクは理解していません・・・
難しく考えずにコピペで使っちゃいましょう!

↓レイヤーマーカーではなく、コンポジションのマーカーを参照できるよう書き換えてみました。
複数レイヤーを同じタイミングでループさせたい場合はこちらの方がラクですね。


loopTime = 0;
numLoop = 0;
keyN = 0;
shiftTime=0;
cycleTime =key(numKeys).time;

if (thisComp.marker.numKeys){
keyN = thisComp.marker.nearestKey(time).index;
if (thisComp.marker.key(keyN).time > time) keyN--;
}

if (keyN > 0) {
numLoop = parseInt(thisComp.marker.key(keyN).comment);
shiftTime = time - thisComp.marker.key(keyN).time;

if (shiftTime < numLoop * cycleTime ) {
loopTime = shiftTime % cycleTime ;
}
}

valueAtTime(loopTime )
 


0 件のコメント:

コメントを投稿