まずはAfter Effectsで気軽に使えるJavascript、「エクスプレッション」に触れてみましょう。
2つのレイヤーを「root」と「goal」として、その間に挟まれたレイヤーをエクスプレッションで整列させてみます。
エクスプレッションにより毎フレーム位置が計算され配置し直されるため、「root」「goal」レイヤーの位置をドラッグやキーフレームで変えると他もきちんと追従してきます。
はじめに
今回の記事で、After Effects内のプロパティに記述できるJavascript、「エクスプレッション」における「位置」など1つのプロパティで複数の値を持つ「配列」についてほんの少し触れ(今回は計算の際に意識しなくて良いレベルなので、詳細は今後の記事にて)、「Javascriptとは、エクスプレッションとはこういうものだ」ということを覚えます。
動画制作ソフトでの位置である「X(横位置)」「Y(縦位置)」の指定方法、処理のされ方をより深く知ることが出来ます。
それではまず「root」と「goal」となるレイヤーと、並ばせたいレイヤーを今回は3つ、合計5つのレイヤーを用意します。
式を考える上でわかりやすいように、rootとなるレイヤーとgoalとなるレイヤーのレイヤー名を変更しておきます。「root」と「goal」です。
レイヤー名の変更は、上図の「goal」レイヤーのようにタイムライン上でレイヤーを選択し、[Enter]キーです。Macでのファイル、フォルダ名変更と同じ要領です(筆者はWindows環境)。
注釈
レイヤーの並びは、タイムラインが右に行くにつれて、人によって右下に配置していく「吊り下げ型」と、右上に向かう「積み上げ型」に分かれますが、私の作るプロジェクトファイルは「積み上げ型」です。基本的に、下が動画の始まりのレイヤー、上が終わりのレイヤーになるよう編集しています。
もちろん、重なりによってレイヤーの見え方が変わってきますので、デザイン上で上下することはありますが、レイヤーを複製や貼付けを行う際に、選択レイヤーの一つ上に作られるのと、次のカットが前のカットを覆い隠すように切り替わらせたいからです。
「吊り下げ型」では、カットが切り替わる際に全レイヤーをスパッと終わらせる必要があり、プロジェクトウィンドウが散らかるのが嫌でプリコンポーズを最低限しかしないことから、このルールに適した作業をしてきた結果身についた癖です。
この環境で説明を行いますので、記事を追って勉強される方は同じ型で倣って頂けると、特に今回の記事のようにレイヤー順序を取り扱う際に混乱が少なくなります。ご了承ください。
位置の考え方
この状態で、rootレイヤーの位置は[217,245]です。
X位置がコンポジションの左上から217px右に、Y位置が245px下にrootレイヤーのアンカーポイントがあります。
この位置とgoalレイヤーのある[580,132]とのXYの差、それぞれ半分が2つのレイヤーの中心だと気づくことができれば、計算式を導き出せます。
中心は、(goalのXY)-(rootのXY)ですね。rootから見たgoalの方向が分かりました。
エクスプレッションでの位置の書き方
エクスプレッション上での位置は[100,200]と書き、プロパティが2つあるわけではなく、「配列」と呼ばれる複数の値が入った1つのカゴの状態です。
2Dの世界を「2次元」、3Dの世界を「3次元」と呼びますが、どちらの世界も位置を表すために必要な次元の数が、呼び名として定着したのですね。2次元はヨコ位置+タテ位置、XとYで2次元。3次元はヨコ位置+タテ位置+奥行き、XとYとZで3次元です。
つまり、レイヤーを3Dレイヤーに変換した途端、Z位置が出現します。
そうすると、今度は[x,y,z]と3次元に合わせて3つの数値を配列として渡さなくてはいけなくなります。
プログラムは正しく書かないと機能しないため、JavascriptとAftere Effectsのプロパティの書き方との2つを覚える外ありません。通常のレイヤーがトランスフォームに含むプロパティは
- アンカーポイント(ヨコpx、タテpx)
- 位置(ヨコpx、タテpx)
- スケール(幅%、高さ%)
- 回転(角度°)
- 不透明度(0~100%)
と、数値が2つ並ぶものと1つのものがあります。角度も数値が2つに見えますが、角度は360以上で繰り上がるだけで1つです。
エクスプレッションは計算結果がプロパティに当てはまるように返さなくてなりません。この1つのプロパティで数値を2つ以上持つ配列にエクスプレッションを適用させたい場合、計算結果が[x,y]と2次元で終わる計算式が必要なのです。
もし自身のプロパティに当てはまらない計算結果が返ってくると、ただエラーで止まる不親切な古いプログラムと違い、After Effects 2020はエラー内容をわかりやすく表示してくれます。
試しに2次元必要な「位置」に1次元の数値を渡してみましょう。
このように、親切に教えてくれます。
実際に組み立てていく
それでは、どんな式が考えられるのか、組み立てていきましょう。
まずは言葉で式を作る
さて、次元の指定方法がわかったところで、先程導き出した式、
(goalのXY)-(rootのXY)
この直線状に均等配置する方法を具体的に言葉の式で説明できるようにします。
言葉の式が思いついていれば、後は計算式に変換するだけです。どんな式になるのか言葉で説明できない状態では、まだ計算式が思いつきません。
まず今回は5つのレイヤーがありますので、それぞれ1/4、2/4、3/4の位置に並べば成功です。
整列するレイヤーは、距離を4つに割った内、自分がn番目かが分かれば良い、ということになります。
rootとgoalの距離の出し方、レイヤーを移動させたい方向が分かりましたので、あとは「自分が何個目のレイヤーか」が判別できれば完成しそうです。
「自分が何個目のレイヤーか」
レイヤーに番号が振られています。これをindexといいます。これはエクスプレッション内でも指定できる数字なので、これを使って式を組み立ててみましょう。これまで集めた情報を整理します。
- 「全部で何個あるか」=rootのindex-goalのindex
- 「自分が何番目か」=rootのindex-自分のindex(1~3)
- 「rootとgoalの距離」=goalの位置-rootの位置
言葉で式にすると…
「自分が何番目か」/「全部で何個あるか」*「rootとgoalの距離」
これで、均等配置ができそうですね!
基準の位置を考慮しなくてはならない
しかし、これでrootからの位置が割り出せそうですが、これでは基準とするスタート位置を考慮していません。[0,0]からの距離となってしまい、コンポジションの左上を基準としてしまいます。実際に上記の考え方でエクスプレッションを作るとこうなります。
並び方は合っているのですが、スタート位置が間違っています。
今回のコンポジションでは、コンポジションの左上から右上に並んでしまいます。rootレイヤーは[0,0]にはないのです。これは単純にrootの位置を足してやれば解決します。
「自分が何番目か」/「全部で何個あるか」*「rootとgoalの距離」+「rootの位置」
これですね。
式の仮組みの完成
上記を細かくすると、
(rootのindex-自分のindex)/(rootのindex-goalのindex)*(goalの位置-rootの位置)+rootの位置
できました。言葉で式の仮組みが完成しました。
言葉の式をエクスプレッションに変換
それではこれをようやくエクスプレッションに変換していきましょう。以下の完成した式を見てください。
(rootのindex-自分のindex)/(rootのindex-goalのindex)*(goalの位置-rootの位置)+rootの位置
↓これが…
(thisComp.layer("root").index-thisLayer.index)/
(thisComp.layer("root").index-thisComp.layer("goal").index)*
(thisComp.layer("goal").transform.position-
thisComp.layer("root").transform.position)+
thisComp.layer("root").transform.position;
こうなります。何が何やらですね。
※閲覧環境によって自動で改行されるかもしれませんが、四則演算の直後以外は改行せず書きます。本来は一つの式なので1行に書きます。ただし、四則演算直後の改行は認められます。読みやすさのため長い計算式を改行する際の参考にしてください。
(thisComp.layer(“root”).index-thisLayer.index)/[改行]
~~~~~
ならOKですが、
(thisComp.[改行]
layer(“root”).index-thisLayer.index)/
これはNGです。エラーとなります。
今回のエクスプレッションで使っているAfter Effects独自のプロパティは6つです。
No. | プロパティ | 意味 |
1. | thisComp | 「このコンポジション」 |
2. | layer(○) | 「レイヤーの番号か”名前”で指定」 |
3. | index | 「レイヤー番号」 |
4. | transform | 「トランスフォーム」 |
5. | position | 「位置」 |
6. | thisLayer | 「自身のレイヤー」 |
日本語の助詞である「の」はJavascriptでは「.」になります。プロパティはフォルダのようなイメージで、正しい順序で住所を指定しなければAfter Effectsに伝わりません。どのプロパティがどう繋がるのかは覚える外ありません。日本の住所と同じで大項目から小項目を繋いでいきます。
そのため、「このコンポジションの”root”レイヤー」は thisComp.layer(“root”) のように記述します。あとは中学生が読めるアルファベットで英語を読むレベルです。
「自分が何番目か」/「全部で何個あるか」*「rootとgoalの距離」+「rootの位置」
この式を見事エクスプレッションに出来ました。
効率的に記述できないか
プログラムはもっと短くできます。「=」を使って自分で独自の「変数」というものを設定できるからです。
例えば
var a=10;
「a」という変数に「10」を代入するという意味です。この記述以降、「a」は「10」と同じ意味を持ちます。
var a=10;
a*2;
すると、これで「20」となります。
var a=thisComp.layer("root").index;
この「a」は、この記述以降「thisComp.layer(“root”).index」と同じ意味になります。
蛇足
Javascriptでは、取りあえず変数に代入すれば、数字でも文字でも指定方法に違いはありません。この柔軟性こそ、これだけプログラム言語として広まった特徴であり、逆に意図しないエラーの元ともなります。
なんらかの原因(大抵は自分の記述方法)により、数字が文字列として代入されてしまえば、正しく演算できなくなります。「1(文字列)+1」=文字列に1を連結させる意味になってしまい、「11」という文字列になるのです。
話が逸れましたが、変数を使うとどうでしょうか。今回作ったエクスプレッションは同じ記述が何度も出てきます。大分短くわかりやすくできそうですよね。次回はこの変数を活かして文法の整頓…といきたいところですが、先に一つ覚えて欲しい記述があります。
var a=thisComp.layer("root").index; // ルートレイヤー
この「//」以降、その行は注釈、コメントを自由に書けるようになります。プログラムを無効化(アウト)させることから「コメントアウト」と言って、プログラムをより読みやすいものにできます。
次回予告
次回はこの「コメント」を先に紹介し、さらに次の記事で「変数」を使ったプログラムの効率化をしていきましょう。
是非、将来的にはエクスプレッションを覚えていって、手作業では作れない面白いアニメーションを作りましょう。
下記リンクから飛べます。
この記事へのコメントはありません。