Using text layers as expression editors in After Effects

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:

Screen Shot 2016-07-23 at 12.36.02 PM

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.

Screen Shot 2016-07-23 at 12.59.24 PM

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.

Screen Shot 2016-07-23 at 12.37.31 PM

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.

One comment

Leave a Reply

Your email address will not be published. Required fields are marked *