pointOnPath()|線に沿って矢印を走らせる、ルートアニメーションの作り方

pointOnPath()で曲線に沿って矢印を移動し、向きも追従させる作例

曲線に沿って矢印が進み、カーブに合わせて向きも変わる。pointOnPath() と tangentOnPath() を使うと、描いたパスを移動ルートとして参照できます。

今回は、丸のパス移動から、地図風のルート案内、描かれる線の先端を矢印が追う作例へ進みます。ルートを描き直しても、位置のキーを作り直さず追従できるのが、この方法の便利なところです。

この記事で使用したAEプロジェクトを無料ダウンロードできます。ダウンロードは記事の最後から。

目次

まずは完成形:丸が線に沿って移動する

CTRLのProgressを0→100へ変更。丸の位置にはキーフレームを打たず、パス上の座標を式で参照しています。 6秒・音声なし。再生ボタンで確認できます。

アニメーションさせるのは、進行率を表す1本のスライダーです。手で位置のキーを並べる代わりに、パスの形と進行率から、現在位置を計算します。

pointOnPath()とtangentOnPath()の役割

書き方何を取り出すか
path.pointOnPath(u)パスの長さに対する割合uの位置座標
path.tangentOnPath(u)その位置でパスが進む方向を表す接線ベクトル
u=0〜10が始点、1が終点。50%なら0.5
route.toComp(…)ルートレイヤー内の座標をコンポジション座標へ変換

進行率は頂点の個数ではなく、パスの長さに対する割合です。4頂点だから各頂点が0・33・66・100%になる、という意味ではありません。開いたパスでは0が最初の頂点、1が最後の頂点です。閉じたパスでは0と1が同じ場所になります。

準備:ルート・進行率・丸の3レイヤーを作る

項目今回の条件
環境After Effects 26.5×89/macOS/JavaScriptエクスプレッションエンジン
コンポジション1280×720/30fps/6秒/8bpc
ROUTEシェイプレイヤー。Routeグループ内にPathという開いたベジェパス1本。塗りなし・線8px
CTRLヌルオブジェクト。Progressという名前のスライダー制御を追加
DOT直径34pxの丸。中心とアンカーポイントを揃える
共通条件2D/親とリンクなし/位置の次元分割なし/追加プラグイン・外部素材なし
  1. 空のシェイプレイヤーを作り、名前をROUTEにします。レイヤーのアンカーポイントと位置を[0, 0]、スケール100%、回転0度へ揃えます。
  2. ROUTEを選び、ペンツールで開いた曲線を描きます。塗りはなし、線は8px。パスが入ったシェイプグループをRoute、その中のパスをPathへ改名します。
  3. Routeグループ内のトランスフォームも、位置[0, 0]・アンカー[0, 0]・スケール100%・回転0度にします。
  4. ヌルを作ってCTRLと命名。「エフェクト」→「エクスプレッション制御」→「スライダー制御」を追加し、エフェクト名をProgressへ変更します。
  5. 別のシェイプレイヤーDOTを作り、楕円34×34pxと塗りを追加。楕円の中心とレイヤーのアンカーポイントを同じ位置に揃えます。
  6. DOTのレイヤー全体の「位置」のストップウォッチをOption/Alt+クリックし、次のコードを貼り付けます。

レイヤー名・グループ名・パス名・エフェクト名は、コードと正確に一致させます。今回の参照先は ROUTE → コンテンツ → Route → Path です。日本語UIの「パス 1」などのままなら、Pathへ改名するか、コード側をその名前へ合わせてください。

コピー用コード1:丸や矢印をパス上へ配置する

var route = thisComp.layer("ROUTE");
var path = route.content("Route").content("Path").path;
var u = clamp(thisComp.layer("CTRL").effect("Progress")(1) / 100, 0, 1);
route.toComp(path.pointOnPath(u));

Progress / 100 で、スライダーの0〜100をパスの0〜1へ変換しています。clamp(..., 0, 1) で範囲を制限するため、スライダーが範囲外でも始点・終点に留まります。

pointOnPath() が返すのはパス側の座標です。ここでは toComp() でコンポジション座標へ変換し、親のないDOTの位置へ渡しています。パスが入ったシェイプグループ内の追加変形までは、この式で変換していません。Routeグループの位置・スケール・回転は上の条件に揃えてください。

Progressを0〜100へ動かす

  1. CTRLのProgressを0にすると、丸がパスの始点に来ることを確認します。50と100でも位置を確認します。
  2. 0.5秒でProgress=0のキーフレームを作ります。
  3. 5.5秒へ移動し、Progress=100のキーフレームを作ります。
  4. 2つのキーをリニアにします。丸の位置にはキーを打たず、Progressだけで再生します。

配布例では冒頭・末尾を止めるため、0秒にも0、6秒にも100のキーを追加しています。0.5〜5.5秒の5秒間が移動部分です。元のパスを変形させない条件では、Progressを一定の速さで変えると、パスの長さに沿ってほぼ一定の速さで進みます。

同じパスで進行率0%、50%、100%の丸の位置を比較。
同じ曲線・同じ丸でProgressだけを変更。50%はパスの長さの中間で、中央の頂点を指定しているわけではありません。

配布AEPではPATH_BASIC_SOURCEを開いて編集します。記事の説明付き動画01_BASIC_PATHは、ソース全体を85%にして見出しと注記を添えたものです。

実践1:地図風ルートで、矢印の向きも追従させる

架空の地図にルートを重ねた作例。位置と向きを同じProgressで制御し、カーブに沿って矢印が回転します。 6秒・音声なし。再生ボタンで確認できます。
  1. DOTの代わりに、右向きの矢印を別シェイプレイヤーで作り、名前をARROWにします。
  2. アンカーポイントツール(Y)で、矢印の先端へアンカーポイントを合わせます。
  3. ARROWのレイヤー全体の「位置」へ、上の位置用コードを貼り付けます。
  4. 同じレイヤーの「回転」へ、次のコードを貼り付けます。
  5. ルートの後ろに道路風の線やブロックを配置し、始点と終点へSTART・GOALの目印を置きます。

コピー用コード2:カーブに合わせて矢印を回転

var route = thisComp.layer("ROUTE");
var path = route.content("Route").content("Path").path;
var u = clamp(thisComp.layer("CTRL").effect("Progress")(1) / 100, 0, 1);
var p = path.pointOnPath(u);
var a = route.toComp(p);
var b = route.toComp(p + path.tangentOnPath(u));
var v = b - a;
radiansToDegrees(Math.atan2(v[1], v[0]));

接線は、その場所でパスが進む方向です。この式では、パス上の点pと「p+接線」の2点をコンポジション座標へ変換し、その差から向きを求めます。Math.atan2() で角度を求め、radiansToDegrees() でAEの回転に使う度数へ変換しています。

位置と回転の両方が同じProgressを参照するので、移動位置と向きが揃います。ルートレイヤー自体を移動・拡大・回転しても、2点を変換することで向きを合わせられます。ただし、今回の式は親のない2Dレイヤー用です。3Dカメラや親レイヤーがある構成は、そのまま当てはめず座標系を揃えてください。

同じ進行率50%、同じ矢印の位置で、回転なしと接線に向きを合わせた状態を比較。
位置・パス・Progressは同じ。回転の式だけをオン/オフしています。右側では矢印の先端がカーブの進行方向を向きます。
項目作例の設定
Progress0秒0/0.5秒0/5.5秒100/6秒100。全キーリニア
ARROW右向き・先端アンカー・塗りあり・親なし・2D
ROUTE開いたパス1本・線8px。グループ変形は初期値
背景AE内で作った架空の地図。実際の場所や道路の案内ではありません
編集先PATH_ARROW_SOURCE。02_MAP_ROUTEでは85%で配置

実践2:描かれる線の先端へ、矢印を連動

Progressを、線のトリミングの終了値と矢印の位置・回転へ共通で使用。矢印の先端が描画の終点に付きます。 6秒・音声なし。再生ボタンで確認できます。
  1. 矢印の位置・回転が動いている状態から、ROUTEのRouteグループを開きます。
  2. グループの「追加」→「パスのトリミング」を追加します。
  3. トリミングの開始を0%、オフセットを0度にします。対象パスは開いた1本だけにします。
  4. トリミングの「終了」へ、次の式を貼り付けます。
  5. CTRLのProgressを再生し、線の終点と矢印の先端が同じ場所に来ることを確認します。

コピー用コード3:線のトリミングも同じ進行率へ

clamp(thisComp.layer("CTRL").effect("Progress")(1), 0, 100);

トリミングの終了は0〜100%、pointOnPathの入力は0〜1です。同じProgressを、線にはそのまま、位置には100で割って渡すのがポイントです。線と矢印へ別々のキーを打たないので、タイミングのずれを減らせます。

配布例の薄い灰色の線は、未描画部分を見せる補助線GUIDEです。GUIDEのPathをROUTEのPathへ連動させ、ルートを描き直した場合も同じ形になるようにしています。演出に不要ならGUIDEを非表示にできます。

項目設定
トリミングの開始0%
トリミングの終了Progressへ連動
オフセット0度
パス開いた1本。複数パスをまとめた場合は同じ対応になるとは限りません
矢印の基準点矢印の先端。中央アンカーのままだと先端位置がずれます
編集先PATH_TRIM_SOURCE。03_DRAW_LINE_ARROWでは85%で配置
3秒時点の実際のAEタイムライン。ヌル、ARROW、ROUTE、GUIDEで構成。
実際のAEタイムライン。3秒時点はProgress=50%。ソース名表示のヌルがCTRLで、矢印・描画線・補助線を別レイヤーに分けています。

ルートを描き直したら、矢印はどうなる?

進行率50%を固定し、パスの頂点位置だけを変えた前後。矢印の位置と向きが新しいパスへ追従。
同じ進行率50%・同じ位置式と回転式のまま、パスの頂点位置だけを変更しています。位置・回転のキーフレーム追加は不要です。

ROUTEのPathを編集すると、式が新しいパスから位置と接線を読み直します。位置キーへパスをコピーする方法と比べて、ルート変更後の貼り直しが要らないのが利点です。

一方、パスを描き直すと全長や長さの配分が変わります。同じ50%でも、画面上の同じ場所や同じ頂点を通るとは限りません。また、ルートレイヤーを縦横で違う比率に拡大した場合、コンポジション上の速さまで一定になる保証はありません。

うまく動かないときに確認するところ

症状確認すること
式の参照エラーROUTE/Route/Path/CTRL/Progressの名前が一致しているか
丸がルートからずれるRouteグループの位置・アンカー・スケール・回転、DOTの親と次元分割を確認
矢印の先端が線からずれるアンカーが矢印の先端にあるか。位置式はレイヤー全体に設定する
矢印が90度ずれる元の矢印が右向きか。上向きなど別の基準方向なら角度の補正が必要
逆向きに進むパスの始点と終点、Progressのキーの方向を確認
角で急に回転する接線が不連続な角では向きが急変するため、ベジェハンドルで曲線を滑らかにする
線と矢印のタイミングがずれる両方とも同じCTRLのProgressを参照し、トリミング開始0・オフセット0か確認
終点で始点へ戻る閉じたパスの0%と100%は同じ位置。今回の作例は開いたパス
マップ背景だけを動かしたい説明付きコンポ内の背景と、ルートを含むSOURCEを区別する

作例プロジェクトをダウンロード

丸のパス移動・地図風ルート・線の先端追従と、3種類の比較を含む編集用プロジェクトです。

項目内容
ファイルpas-pointonpath-v1.0.zip/100.2KB/v1.0
同梱内容編集可能なAEP・はじめに.txt・コピー用コード
AE26.5×89/JavaScriptエクスプレッションエンジン
フォントHiragino Sans W6・Arial Bold。フォント本体は未同梱。ない場合は置換してください
素材AE内の図形・文字のみ。外部参照・追加プラグイン不要
利用条件学習・個人制作での利用と改変は可。商用利用は個別相談

商用利用のご相談はお問い合わせへ。ほかの表現はAEエクスプレッション集から探せます。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

フリーランスとしてPASを運営し、モーションデザインや映像制作を中心に活動しています。

映像をつくることだけでなく、情報をどう捉え、どう組み替え、どう伝えるかという「編集」に関心があります。

また、越境学習に関わる現場にも参加し、対話や問いを通じた学びの場づくりにも取り組んでいます。

コメント

コメントする

目次