【エクスプレッション】pointOnPathを使ってみよう

pointOnPathはパスのすきな場所の位置、tangentOnPathは接線(パスの向かっている方向への線)、normalOnPathは法線(接線を90度回転した線)を得られます。が、そのまま使うとあんまり期待した通りの結果にならないので、使い方のコツを描いていきます。

■まとめ

  • pointOnPathの座標系はシェイプトランスフォームの座標なので、他レイヤーで使うには座標変換が必要。
  • tangentOnPathはpointOnPathの位置を[0,0]として、そこから進行方向へ1進んだ位置を出すので、使うときはpointOnPathにtangentOnPathを足して使う。
  • normalOnPathもtangentOnPathと同様。

色々と例を作るので、見ていきましょう。

その1:ヌルをパスに沿わせる(ヌル以外のレイヤーでも可)

STEP
準備。

まずはどんな形でもよいので、画面上にシェイプレイヤーのパスを作ります。
そしてヌルも作り、ヌルに『スライダー制御』を1つ適用しておきます。

STEP
ヌルにエクスプレッションを適用。

ヌルの位置プロパティに以下のエクスプレッションを適用します。

mLyr = thisComp.layer("シェイプレイヤー 1");
mPath = mLyr.content("シェイプ 1").content("パス 1").path;
mSldr = effect("スライダー制御")("スライダー");
mRatio = linear( mSldr, 0,100,0,1 );
mPtOnPath = mPath.pointOnPath(mRatio);
mLyr.toComp(mPtOnPath);

*名前はピックウィップで得る等、適宜変えてください。

STEP
スライダー制御で動かす。

スライダー制御を0~100の範囲で動かすと、パスが沿います!

■解説
エクスプレッションの解説をします。
mLyr、mPath、mSldrはそれぞれシェイプレイヤー、そのシェイプレイヤーにあるパス、スライダー制御です。使うのでとりあえず変数に入れたということですね。
mRatioはpointOnPath()のカッコの中に入れる割合です。直接数値を入れてもいいのですが、せっかくなのでスライダー制御で動かすためにスライダー制御の値を入れます。が、pointOnPath()のカッコ内には始点0~終点1の範囲を入れるので、スライダー制御をドラッグして動かすには範囲が狭すぎます。なので、mRatio = linear( mSldr, 0, 100, 0, 1 )で、「スライダー制御が0~100のとき、0~1になるようなmRatio」を作ったということです。
mPtOnPathはpointOnPath()の値ですね。前述の通り、()にはmRatioを入れます。
ここからが本題です。
mPtOnPathにはパスに沿った位置が入りましたが、その座標はパスのシェイプトランスフォームの座標なんですね。対してヌル位置はコンポ座標なので、変換しないと使えないということです。
(座標変換についてはこちら
幸いこのパスはシェイプトランスフォームをデフォルト値から変えていないので、シェイプトランスフォームの座標といってもレイヤー座標と変わりないです。なので、レイヤー座標からコンポ座標への変換toComp()が使えるということですね。
レイヤー〇〇.toComp(レイヤー〇〇の座標)という形で使います。pointOnPath()は今回使ったシェイプレイヤーのレイヤー座標なので、toCompの前にmLyr.と書くのを忘れないようにしてください。省略すると、aeが勝手に『このヌル.toComp()』と解釈してしまうので注意が必要です。

「シェイプのトランスフォームも使いたいよ!」という人は、ここのtoShapeLayerCoord関数をエクスプレッションの一番最初に入れておいて、今回の例文エクスプレッションの最後の
mLyr.toComp(mPtOnPath);

mLyr.toComp(mToShpLyrCoord(mPath, mPtOnPath));
に変えれば問題なしです!

その2:ヌルをパスのトリミングに沿わせる(ヌル以外のレイヤーでも可)

STEP
準備。

まずはどんな形でもよいので、画面上にシェイプレイヤーのパスを作ります。
そしてヌルも作ります。
パスの下に『パスのトリミング』を追加しておきます。
パスのトリミングはパスと同じグループ内に入れてください。

*例その1からスライダー制御を消して、パスのトリミングを加えただけです。

STEP
ヌルにエクスプレッションを適用。

ヌルの位置プロパティに以下のエクスプレッションを適用します。
*例1と変わっているのは3行目だけです。

mLyr = thisComp.layer("シェイプレイヤー 1");
mPath = mLyr.content("シェイプ 1").content("パス 1").path;
mTrim = mLyr.content("シェイプ 1").content("パスのトリミング 1").end;
mRatio = linear( mTrim , 0,100,0,1 );
mPtOnPath = mPath.pointOnPath(mRatio);
mLyr.toComp(mPtOnPath);

*名前はピックウィップで得る等、適宜変えてください。

STEP
パスのトリミングの終点を動かす。

パスのトリミングの終点に合わせてヌルが動きます!

■解説
ヌルのコントローラーをスライダー制御からパスのトリミングに変えただけです。
『パスのトリミング』は0~100で始点~終点を行き来するのに対し、pointOnPath()は0~1で始点終点を行き来するので、mRatio = linear( mTrim , 0,100,0,1 )で「パスのトリミングが0~100のとき、0~1になるmRatioというもの」を作り、それをpointOnPath()のカッコの中に入れればちょうど対応する、ということですね。

例では終点を参照しましたが、始点にしたい場合は
mTrim = mLyr.content(“シェイプ 1”).content(“パスのトリミング 1”).end;
の最後を
startに書き換えればよいだけです!

その3:normalOnPathも使って目盛りみたくする

STEP
準備。

まずはどんな形でもよいので、画面上にシェイプレイヤーのパス 1を作ります。
パス 1の下に『パスのトリミング』を追加します。
その下に点1つだけでよいので新たなパス 2を作ります。
シェイプレイヤーにスライダー制御も適用してください。

*『パスのトリミング』とパス 2は、パス 1と同じグループ内に入れてください。
*パス 2が『パスのトリミング』の影響を受けないよう、パス 2は『パスのトリミング』の下にしてください。
*今回のスライダー制御は今までの例と違う使い方です。

STEP
パス 2のパスにエクスプレッションを適用。

パス 2のパスに以下のエクスプレッションを適用します。

mPath = content("シェイプ 1").content("パス 1").path;
mTrim = content("シェイプ 1").content("パスのトリミング 1").end;
mRatio = linear( mTrim, 0,100,0.001,1 );
mPtCt = mPath.pointOnPath(mRatio);

mSldr = effect("スライダー制御")("スライダー");
mPtNml = mPath.normalOnPath(mRatio);
mPt1 = mPtCt + ( mPtNml * mSldr);
mPt2 = mPtCt - ( mPtNml * mSldr);

createPath([ mPt1,mPtCt,mPt2], [], [], false);

*名前はピックウィップで得る等、適宜変えてください。

STEP
パスのトリミングの終点を動かす。

パスのトリミングの終点に合わせて目盛りのようなパス 2が動きます!
スライダー制御で幅も調節可能です。


■解説
4行目までは今までの例と一緒ですね。
mPtCtがパス 1に沿った点です。今回は同じ座標内のパス 2に値を渡しているので、座標変換はいりません。

6~9行目の説明です。
normalOnPath()で、パスの進行方向から1進み、それ90度回転させた点が得られます。『目盛りみたいに横に伸ばしたところの点』ってことですね。「90度ってどっちに?」と思いますが、パスの進行方向(パスの点番号ゼロ~ラストへ向かう方向)の右へ90度のようです。右周りで+なのは回転プロパティの+-と一緒ですね。
まずはnormalOnPath(mRatio)で、pointOnPath(mRatio)と同じ場所の値を得ます。
しかし、normalOnPath()はpointOnPath()を原点とした位置なので、そのままでは使えません。なので使うときはpointOnPath() + normalOnPath()と書けば、画面上での位置が得られます。
また、得られるのは『1』進んだ箇所なので、スライダー制御を使って長さをもっと増やせるようにします。
それが8行目の
mPt1 = mPtCt + ( mPtNml * mSldr);
つまり、mPt1 = ポイントオンパス + ( ノーマルオンパス × スライダー制御 )ですね。
そして9行目ですが、
今回はマイナス方向にも目盛りみたいなのを作りたいので、
ポイントオンパス - ( ノーマルオンパス × スライダー制御 )で
「ポイントオンパスから、ノーマルオンパスのマイナス方向へ進ませた位置」を得ているわけです。

最後の11行目で、作った3点をつなげてパスを作っています。
ほんとは今回はmPtCtはいらないんですけど、せっかく作ったので入れてあります。

そして、「4行目までは今までの例と一緒」と書きましたが、実はちょっとだけ変えてあります。
mRatio = linear( mTrim, 0,100,0.001,1 );
なんですが、0~100を0~1ではなく0.001~1にしてあるんですね。
これは「パスは始点の時点では、線ではなくて点なので方向もない。なので接線も法線もない」ということで、ゼロを入れると消えてしまうんですね。消えてしまうというか、[0,0]となり、ポイントオンパスと同じ位置になるということです。
なので、ほんのちょっと実際の位置とズレますが、ゼロではなく0.001を入れているというわけです。
「始点のときは消したい」という場合はゼロを入れてしまえば消えます。

その4:tangentOnPathも使って+印目盛りみたくする

STEP
準備。

例その3で作ったものを使います。
パス 2をコピペかctrlDでパス 3を作ります。

STEP
パス 3のパスにエクスプレッションを適用。

パス 3のパスに以下のエクスプレッションを適用します。
*変わっているのは7行目だけです。

mPath = content("シェイプ 1").content("パス 1").path;
mRatio = content("シェイプ 1").content("パスのトリミング 1").end;
mRatio = linear( mRatio, 0,100,0.001,1 );
mPtCt = mPath.pointOnPath(mRatio);

mSldr = effect("スライダー制御")("スライダー");
mPtNml = mPath.tangentOnPath(mRatio);
mPt1 = mPtCt + ( mPtNml * mSldr);
mPt2 = mPtCt - ( mPtNml * mSldr);

createPath([ mPt1,mPtCt,mPt2], [], [], false);

*名前はピックウィップで得る等、適宜変えてください。

STEP
パスのトリミングの終点を動かす。

パスのトリミングの終点に合わせて+印となったパス 2&3が動きます!
スライダー制御で幅も調節可能です。

■解説
パスを増やし、normalOnPath()をtangentOnPath()にしただけです。
normalOnPathに加えてパスの進行方向前後にも線が増え、+印のようになりましたね!

以上です!
この例だけでなく色々な表現に発展しうるメソッドだと思いますので、ご参考ください!

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