You can use text layers in After Effects as expression editors
which means, among other things that a whole lot of layers can use the same expression.
This has some big advantages: expressions update as you type, which gives you instant feedback. You can see and edit your expression right in the composition viewer, without having to hunt for the property with the expression, and you don’t have to squint to read the default expression editor font. And as I’ve just discovered, by animating the text source you can change the expression over time, without having to use if/then statements.
This is a technique that I think I invented, I haven’t seen anyone else doing it. Let me know if you thought of it years ago.
There’s a few hidden JavaScript gems buried in After Effects. One is that you can use the global eval()
method to drive expressions from text sources. For example you can have expressions in a text file and use evalFile()
to pull the expressions from the file. The big down-side to this is that the file is evaluated every time the layer is rendered, so it is read from disk at least once each frame – more if you use motion blur. That could mean a lot of disk-thrashing, with the attendant slowdown. Maybe not a great idea.
More useful is the ability to use the text source of a text layer as the expression. This seems like it should be straight forward, but there’s a trick to it.
Setting up a text layer as the source for an expression
So here you have a layer with an expression on it:
This expression just puts the solid at a random point on the screen. If we duplicate the red layer all the duplicates will have their own individual random position. This is the basis for build-your-own particle effects.
Now if I had dozens or hundreds of copies of the red solid and wanted to update the expression I’d have to copy and paste it to all my layers before I could see it in action. Easy enough to do if the expression is just for the position property, but if it’s on an effect then you have to select the property of each layer to paste it on to, to avoid duplicating the effect. Can be quite tedious, so usually I would delete all the duplicate layers and re-duplicate my original. And you have to do this every time you update the expression.
So here’s where the magic starts. What if I can make a text layer whose contents are the expression that I want use for the position of my solid layers, meaning that any update to the expression will happen on all the solids as I type?
First add a text layer, and paste the expression into it. Now by default the name of the text layer is the contents, so your text layer’s name will now be really long. For convenience I rename it to something like “expressionSource”, or more usefully, the name of the property I’m controlling, like “jellyfish size” or “trumpet position” &c.
On the property that you want to control you need to evaluate the contents of the text layer using eval()
. If you use the pickWhip on the text source it returns thisComp.layer("expressionSource").text.sourceText
You would think that this was the raw text content of the text layer, but it’s not, and it won’t work. Turns out it’s a formatted TextProperty
object that contains text, plus some other stuff including formatting. That’s how you can have text layers with some letters in different styles from the others. Remembering my experience with extendScript I know that to get the value of a property you use the .value
property of the property. So the expression should look like this:
exp = thisComp.layer("expressionSource").text.sourceText.value; eval(exp)
This goes on any property you want to drive with your text layer. When you type an expression into your text layer it will be evaluated and the value of that property will be set to the result.
You probably want to turn your text layer into a guide layer at this point, so you can see it but it won’t render.
Here’s me mucking around with an expression, and having it update in real time.
Using data from an external file to drive expressions in AE – blob
[…] Another method is to use a text layer as your expression source. I think I invented this, I haven’t been able to find anyone else who has published the method. Details here […]
Nathan Broderick
Wow. I am blown away. This is what was missing in my life.
stib
There’s a better way to do it—see for how to use the global $ object to achieve the same result.