All our expressions are written for the newer JavaScript Expressions Engine

Blog

How to attach layers to the end of a path

Photo of Tim Haywood
Tim Haywood

|

May 17, 2021

The new path expressions added in After Effects v15 allow you to get a point and it's tangents along a path, using the pointOnPath() and tangentOnPath() methods.

  • pointOnPath() to get the position value
  • tangentOnPath() to get the rotation value, so the layer auto-orients along the path direction

This is perfect for attaching arrow heads to the end of lines, or hands to the end of arms. It also works well when using trim paths to animate the path.

This technique comes from the talented Florian Zeitler, who posted it in the After Effects discord.

Getting the position

pointOnPath() is a method on path properties, and returns the [x, y] coordinate array for a point along a path. It accepts one argument, which is how far along the path to get the point, from 0 to 1.

diagram of a line, showing a point halfway along and the code pointOnPath(0.5)

Since pointOnPath() is a method of path properties, it needs to be prefixed with the path you want to use. For example:

js
thisComp.layer("path").content("Path 1").path.pointOnPath(1);

Here we're referencing the path "Path 1", and getting the point at the end of the path by passing 1 into pointOnPath().

If you place this value on a position property, you will notice that the layer doesn't line up with the path.

pointOnPath() returns the point in layer space, which you can convert to composition space with toComp().

You can convert the returned value to comp space by passing it into the toComp() method of the path layer.

position

js
const pathLayer = thisComp.layer("path");
// The position of the point along the path
// in layer space
const pointOnPath = pathLayer
.content("Path Group") // The shape group
.content("Path 1") // The path group
.path.pointOnPath(1);
// Convert the point to comp space
pathLayer.toComp(pointOnPath);

Make sure to add the .path to reference the path itself, rather than the path group.

When using trim paths, you pass the trim amount to pointOnPath() to get the point at the end of the animated path.

position

js
const pathLayer = thisComp.layer("path");
// The trim paths end amount, divided by 100
// to map it to 0 -> 1
const trimAmount =
pathLayer.content("Path Group").content("Trim Paths 1").end.value / 100;
// The position of the point along the path
// in layer space
const pointOnPath = pathLayer
.content("Path Group")
.content("Path 1")
.path.pointOnPath(trimAmount); // Pass in the trim amount
// Convert the point to comp space
pathLayer.toComp(pointOnPath);

Rotation

tangentOnPath() works much like pointOnPath(), but rather than a point along the path it returns the path tangent at the given progress.

The path tangent is a straight line that "just touches" a given point on the curve, and indicates the direction of the path at that point.

diagram showing a path, it's tangent angle theta, and theta equals atan2(tan y, tan z)

You can then use this tangent value to get the angle of the path at this point, using trigonometry. There is a function for this calculation built into JavaScript, Math.atan2().

This function returns the angle of a given point, in radians.

js
const angleInRadians = Math.atan2(y, x);

Make sure to pass in the y value as the first argument, as the x value as the second.

You can then convert the value to degrees with the function radiansToDegrees():

js
const angleInDegrees = radiansToDegrees(Math.atan2(y, x));

This is the full rotation expression, again getting the point according to the trim paths value.

rotation

js
const pathLayer = thisComp.layer("path");
// The trim paths end amount
const trimAmount =
pathLayer.content("Path Group").content("Trim Paths 1").end.value / 100;
// Destructure x and y tangents at the point
const [tangentX, tangentY] = pathLayer
.content("Path Group")
.content("Path 1")
.path.tangentOnPath(trimAmount);
// Calculate the angle based on the tangent
radiansToDegrees(Math.atan2(tangentY, tangentX));

Blog

For enquiries contact us at hey@motiondeveloper.com