Back to Blog

Everything About Expressions You Didn't Know...Part III: The Return of Math

By Zack Lovatt
After Effects

Enhance your expression knowledge with a close look at the Javascript Math, Random Numbers, and Path Properties Expression Language menus.

The Expression Language Menu holds a lot of little pieces for you to assemble. Where do you even start?! This series will walk you through each category and highlight a few unexpected items in each, leaving you better equipped to start expressing yourself via expressions.
expressions-3-article.jpg
These menus are all about working with numbers and properties. Unsurprising, maybe, as it's in the name. With these expressions you can exert some serious control of your animations without the need for tedious looping. We're going to cover:
  • Javascript Math
  • Random Numbers
  • Path Property
Article 3 Menu.png

Javascript Math

expressions-explained-part3-1.jpg
This whole section is directly from Javascript, with nothing specific to AE added in. As such, there are a million resources for it online!
With that said, we're going to cover working with it specifically for AE, focusing on:
  • Snapping numbers to the nearest whole digit
  • Getting the minimum or maximum value in a set
  • Mathemagically animating something in a perfect wave
  • For more information, see the MDN Javascript Math reference
I can already tell that you + this section will = a good, informative time, so let's explore Javascript Math.

Rounding Numbers

expressions-explained-part3-3.jpg
When we say 'rounding', we mean snapping a number with decimal places to the nearest whole number— 1.234 will round down to 1, 2.5 will round up to 3, 133.7 will round up to 134, etc.
Most of the time you'll want to use this when displaying text on screen without having a bajillion trailing digits, but one cooler use is to pair it with Time to have a number snap every second.
In this example, we'll apply time to the second hand of a stopwatch. First, we'll show this without the rounding:
const multiplier = 5; time * multiplier;
java4.gif
Smooth as a buttered biscuit
You can see that the hand is smoothly moving in a circle. This is what we'd expect! Time moves smoothly, so the clock hand moves smoothly too.
But if we round this value, the clock hand will only snap every second, as opposed to evenly moving:
const multiplier = 5; Math.round(time) * multiplier;
java2.gif
Congratulations, you've turned a $500 automatic watch into a $13 mechanical
Now it's worth pointing out that this will snap at the midway mark between seconds, as opposed to the start; for more accuracy, use Math.floor() in place of Math.round() if you decide that really matters.

Finding Highest and Lowest Values

expressions-explained-part3-2.jpg
Let's say you've got a bunch of different numbers, and want to find the largest one of the group...or the smallest!
There are a few clever (and a lot of not-so-clever) ways to accomplish this, but the built-in Math.min() and Math.max() functions are by far the simplest.
In this case, we've got a few cars on a racetrack, and we'd like to indicate which car is currently winning without needing to do any sort of manual keyframing work on our label.
We can accomplish this by first getting all of the X positions of each car, feeding those into Math.max(), and using that value to drive the position of our label.
const car1X = thisComp.layer("Car 1").position[0]; const car2X = thisComp.layer("Car 2").position[0]; const car3X = thisComp.layer("Car 3").position[0]; const car4X = thisComp.layer("Car 4").position[0]; const car5X = thisComp.layer("Car 5").position[0];
Math.max(car1X, car2X, car3X, car4X, car5X);
java5.gif
If we wanted to attach our label to the losing car, we can simply swap Math.max() with Math.min() and that'd be that!
java3.gif
rickybobby.gif

Easily Waving

expressions-explained-part3-4.jpg
If you're looking for some sinfully, sinuously smooth curves, you've come to the right place.
We can use the Math.sin() function to generate a sine wave from any number, which is preeeetty much just a nerdy way to smoothly sway a number from -1 to +1, forever and ever and ever.
NOW that may not sound exciting, but it is! Er, it can be!
By controlling the wave with time—which always increases—we can have it repeat forever at a consistent speed. By multiplying the result by, say, 30, we can have it go from -30 to +30, forever. By multiplying the speed higher, we can make it move faster!
All this to say: this is a function to automate extremely controllable waving animation for us with no keyframes. This metronome has no keyframes, but will tick and tock all day long:
const speed = time * 2.1; const amount = 30;
Math.sin(speed) * amount;
java1.gif
No need for looping expressions, a billion keyframes, or anything of the sort.
Adding to Good Times
All of this together clearly adds up to some good times. No longer will you need to divide your focus or subtract distractions from your workday; you can practically calculate the benefits right from the get go.
From zero to AE hero, Javascript Math will keep you even. Or odd. Care for some Pi, anyone?

Random Numbers

expressions-explained-part3-5.jpg
Sometimes in AE you want to mix things up a little, create some chaos—that's where the Random Numbers category comes in!
Of course, we don't want too much chaos—that'd be reckless. Thankfully, we can use the functions in this category to control the exact limits to our randomness.
We’ll look at:
So with that said, let's dig into 41, 20, 110, 0.1231... sorry, got carried away. Let's dig into Random Numbers!

Generating New Random Numbers with seedRandom()

expressions-explained-part3-6.jpg
Now, we all know how to get some smooth random motion-- that's wiggle()! You've seen this before so we're gonna skip over that.
Instead, I want to answer a common question that comes up:
"I like the overall feeling of the movement, but I want it... slightly different. Is this possible?"*
*okay I've never actually been asked this, BUT it's something that I've personally faced.
To solve this we'll use seedRandom(), which effectively lets us take a dice roll, and... roll it again. We're still working with a 6-sided die (that's a "d6" in geek parlance), we just want to get a different result!
Now, this is a special type of expression. You don't assign it to anything—it just sits at the top of your expression and modifies everything below...like an adjustment layer for your code, modifying anything beneath it.
To generate a brand new wiggle without needing to make new layers, we can put this expression onto position, and every time we change the number in the seedRandom() we'll get a whole new wiggle:
seedRandom(12345); wiggle(0.5, 100);
rannum2.gif

Generating New Randomness Per Layer

expressions-explained-part3-7.jpg
In this sample, we've got a whole bunch of layers and we want each one to have a uniquely random opacity...using ONLY ONE EXPRESSION!
To accomplish this, we'll use our friend seedRandom() from above but add in a second option, timeless, which tells AE to lock in the values it's got.
And instead of giving in a number for the first option, we'll give it index, which is the layer's # in your timeline.
We'll add this to each layer's Opacity to get this done:
seedRandom(index, true); random(0, 100);
rannum1.png
That's, like, totally random!
This is only a short look at what Random Numbers can do for you! There are plenty of other random functions here to take a look at, all with their own peculiarities.

Path Property

expressions-explained-part3-8.jpg
Shape layers are big these days. With the amount of 2D-centric animation flying about, a lot of emphasis gets placed on shape paths.
This section is going to look into some of the possible ways to use expressions with both shape & mask paths, unlocking some cool features that would otherwise be inaccessible or just fairly tedious to build by hand.
We'll look at:
Without further ado let's walk down this path and explore the Path Property submenu.

Copying Shape Paths by Expressions

expressions-explained-part3-9.jpg
All path properties have a special function called points(), which returns all of the positions of all of the points on a path!
With this, we can have one layer grab the points from another layer, and create a path from that.
const driverLayer = thisComp.layer("Driver"); const driverPath = driverLayer.content("Path 1").path; const driverPoints = driverPath.points();
createPath(driverPoints);
pathprop3.gif
Aaaaaaaand presto! Two paths for the price of one.

Attaching Layers to Shape Paths

future-of-education-13.jpg
One of the most common AE tasks that expressions can solve is being able to take a layer and attach it to a shape path.
Now, the built-in 'nulls follow shapes' panel can help with this, but it can be fairly clunky and bloated when you're just trying to accomplish something simple.
We can build the main part of this using pointOnPath(), a function that you give a specific % of completion along the path, and it'll return the X and Y coordinates of the corresponding point on the path at that percent.
Think of it like this—a straight line from [0, 0] to [100, 0]. 0% of the way along is [0, 0]. 50% of the way is [50, 0], and 100% is [100, 0].
That math is easy, but if we have some long windy path, we can't really compute this ourselves!
const driverLayer = thisComp.layer("Driver"); const driverPath = driverLayer.content("Path 1").path; const progress = effect("Progress")("Slider");
const pointOnPath = driverPath.pointOnPath(progress); driverLayer.toComp(pointOnPath);
pathprop2.gif
Now we can animate a simple slider, and have our other layer follow the path all the way along it.

Connecting Comp Layers with Shape Paths

expressions-explained-part3-11.jpg
Not only can we get path info and stick things to it, we can actually make our own brand spankin' new paths right from an expression!
Now this expression has got a lot going on, but the idea is that we can leverage a function called pointOnPath() and pass it in a list of points, and it's going to make a brand new shape path for us.
In this example, this expression on the Path property is going to connect all of the layers in our comp with a new shape, that will always be updating no matter where and how our other layers move.
const points = [];
for (let ii = index + 1; ii <= thisComp.numLayers; ii++) {   const layer = thisComp.layer(ii);   const layerPos = layer.position;   const layerPosInShapeSpace = fromComp(layerPos);
  points.push(layerPosInShapeSpace); }
createPath(points);
pathprop1.gif
As we add or remove layers, the path will update live to connect ALL the dots.

Walk Your Own Path

expressions-explained-part3-12.jpg
The Path Property submenu is one of the more recent additions to AE, and this is just a small snippet at what it offers.
Now that we've seen how to clone paths, fix things to them, and make them from scratch, you'll be better aware of the possibilities when dynamic paths come up in your own projects.

Expression Session

If you're ready to dive into some radioactive goop and gain a new superpower, don't do that! It sounds dangerous. Instead, check out Expression Session!
Expression Session will teach you how to approach, write and implement expressions in After Effects. Over the course of 12 weeks, you'll go from rookie to seasoned coder.