After Effects Expressions Cheat Sheet
I’ve put together a list of After Effects expressions that simplify my workflow. You won’t find basics like
Most of these expressions are taken from the web and adapted to fit my needs, with only a few being entirely my own. I’ve included links to credit the authors where relevant.
Adaptive Text Box
Resize a shape layer dynamically to match its text length.
Create a rectangle shape and add a text layer above it.
Apply this expression to the
margin_width = 60;
margin_height = 40;
text_width = thisComp.layer(index-1).sourceRectAtTime().width;
text_height = thisComp.layer(index-1).sourceRectAtTime().height;
box_width = text_width + margin_width*2;
box_height = text_height + margin_height*2;
[box_width, box_height]
For multi-line text, apply this additional expression to the
x = value[0];
y = content("Rectangle 1").content("Rectangle Path 1").size[1]/2;
[x,y]
Animated Wiggle
Easily animate wiggle using two sliders: one controls the frequency, and the other controls the amplitude. For the best results, animate only amplitude.
Add two
w_freq = effect("Slider Control")("Slider");
w_amplitude = effect("Slider Control 2")("Slider");
wiggle(w_freq,w_amplitude)
Looping Wiggle
With this expression, wiggle starts and ends at the same point.
If it doesn’t loop correctly, it’s likely because the loop time is too short for wiggle to return to the starting point. Just increase
freq = 1;
amp = 65;
startTime = 0; // Loop start time
loopTime = 3; // Loop duration in seconds
t = (time+startTime) % loopTime;
wiggle1 = wiggle(freq, amp, 1, 0.5, t);
wiggle2 = wiggle(freq, amp, 1, 0.5, t - loopTime);
linear(t, 0, loopTime, wiggle1, wiggle2)
Pin Shape Layer to One Side
Keep one of the shape’s sides fixed while adjusting the
Apply this expression to the
pinTo = "left"; // top, bottom, right or left
chosenShape = content("Rectangle 1").content("Rectangle Path 1");
if (pinTo == "top"){
x = chosenShape.position[0];
y = chosenShape.position[1]+chosenShape.size[1]/2;
}
else if (pinTo == "bottom"){
x = chosenShape.position[0];
y = chosenShape.position[1]-chosenShape.size[1]/2;
}
else if (pinTo == "right"){
x = chosenShape.position[0]-chosenShape.size[0]/2
y = chosenShape.position[1]
}
else if (pinTo == "left"){
x = chosenShape.position[0]+chosenShape.size[0]/2;
y = chosenShape.position[1]
}
[x,y]
Rolling Circle and Square Rig
Rolling Circle
Apply this to the
transform.position[0]-(content("Ellipse 1").content("Ellipse Path 1").size[0]/2)-transform.position[0]/2
Rolling Square
This expression works with shapes, layers and compositions.
Apply the expression to the
targetLayer = thisLayer;
squareSize = targetLayer.sourceRectAtTime().width;
squareDiag = (Math.sqrt(2)*squareSize)/2/3.5;
try{
squareOffset = effect("Slider Control")("Slider");
}
catch(err) {
squareOffset = 0;
}
rot=transform.rotation;
scl=transform.scale[0]/100;
w=(squareSize/2)*scl;
r=(degreesToRadians(rot))*2;
t=transform.position;
[t[0]+w*rot/45,t[1]-(Math.abs((squareDiag+squareOffset)*Math.sin(r)))*scl];
Based on Mikey Borup’s expression
Stepped Rotation
An alternative to
Apply to the
angle = 15; // Rotation angle per second
rotateDuration = 10; // Duration of rotation in frames
rotateDurationFr = rotateDuration/(1/thisComp.frameDuration);
wholeSecond = Math.floor(time);
startAngle = wholeSecond * angle;
ease(time, wholeSecond, wholeSecond + rotateDurationFr, startAngle, startAngle + angle)
Advanced Stepped Rotation
A more customizable version of the stepped rotation expression.
Apply to the
angle = 15; // Rotation angle per second
rotateDuration = 6; // Duration of rotation in frames
timeStop = 5; // Stop duration between rotations
offset = 0; // Offset of the initial frame
fr = timeToFrames(time)+offset;
cycle = timeStop+rotateDuration;
n = Math.floor(fr/cycle);
cur_phase = fr-n*cycle;
if((cur_phase)>timeStop){
angle*n+(cur_phase-timeStop)*angle/rotateDuration;
}
else{
angle*n;
}
Maintain Scale When Parented
When you parent one object to another and scale the parent, both layers will scale. This expression prevents the child layer from scaling and only moves it by position.
Apply to the layer’s
s = [];
ps = parent.transform.scale.value;
for (i = 0; i < ps.length; i++){
s[i] = value[i]*100/ps[i];
}
s
Checkbox Switcher
Toggle any value with a checkbox.
Add a
Apply this expression to a parameter you want to control:
if (effect("Checkbox Control")(1) == 0) 0 else 100
Shape Layer Loop
Standard
Apply to the
try{
pingPong = false; // Set to true if pingPong is needed
timeStart = thisProperty.key(1).time;
duration = thisProperty.key(thisProperty.numKeys).time-timeStart;
quant=Math.floor((time-timeStart)/duration);
if(quant<0) quant = 0
if(quant%2 == 1 && pingPong == true){
t = 2*timeStart+ (quant+1)*duration - time;
}
else{
t = time-quant*duration;
}
}
catch(err){
t = time;
}
thisProperty.valueAtTime(t)
Range Mapper
Remap input values to a different output range.
Add a
input = effect("Slider Control")("Slider");
inputLow = 0;
inputHigh = 100;
outputLow = 450;
outputHigh = 650;
linear(input,inputLow,inputHigh,outputLow,outputHigh)
Maintain Stroke Width When Scaling
Keep a constant stroke width when scaling a shape.
Apply this to the
value / length(toComp([0,0]), toComp([0.7071,0.7071])) || 0.001;
Counters
A collection of 6 counter expressions for various use cases. All of these counters are basically text layers linked to slider controls, which can be keyframed.
1. Simple Counter
Displays numbers with a fixed decimal place.
Add a
parseFloat(effect("Slider Control")("Slider")).toFixed(2)
2. Comma Separator Counter
Replaces the decimal point with a comma. If you happen to need a similar setup with more customization, it’s right here.
Add a
c = parseFloat(effect("Slider Control")("Slider")).toFixed(2);
c.toString().replace(".", ",")
3. Counter with Additional Symbols
Adds symbols like
Add a
"+"+parseFloat(effect("Slider Control")("Slider")).toFixed(2)+"%"
4. Counter with Leading Zeros
Displays numbers like
Add a
zerosAmount = 3;
var slider = effect("Slider Control")("Slider");
function padStart(string, targetLength, character) {
string = (string instanceof String) ? string : string.toString();
targetLength = targetLength >> 0;
character = character || ' ';
while (string.length < targetLength) {
string = character + string;
}
return string;
};
if (slider >= 0) {
zeroAmount = zerosAmount + 1;
paddedString = padStart(parseFloat(slider.value).toFixed(0), zerosAmount, '0');
}
else {
paddedString = '-0'+padStart(parseFloat(slider.value).toFixed(0)*-1, zerosAmount, '0');
}
paddedString;
Based on Tomas Sinkunas’ expression
5. Digit Grouping Counter
Adds spacing to group digits, turning
Add a
num = parseFloat(effect("Slider Control")("Slider")).toFixed(0);
str = isNaN(num) ? "" : (num * 1 + "");
str.replace(/(\d)(?=(\d\d\d)+([^\d]|$))/g, '$1 ');
6. Large Number Counter:
For values above 1,000,000, use
Add an
number = Math.round(effect("Angle Control")("Angle")/360);
n="" + number;
s="";
for(i=0, l=n.length; i<l; i++){
if(s && s!="-" && (l-i)%3 ==0)
s+=" ";
s += n[i];
}
s;
Various Mini Expressions
And finally, 4 useful mini-expressions that often come in handy.
1. Link to Layer Above or Below
It’s not a complete expression, but only part of it. Instead of linking one layer to another using its name, it is sometimes more convenient to link to a layer above or below the layer with the expression.
In the example, I link the box’s layer position to any layer above. To parent to a layer below instead, use
thisComp.layer(index-1)
2. Constantly Accelerating Rotation
Add this to
time*time*time*time
3. Keyframes with time*n
Add constant motion while still allowing keyframes.
value+time*11
4. Link Gradient Ramp to Layer
Prevent a gradient ramp from shifting when moving the layer. Apply to the
toComp(value)
That’s it! This collection includes 23 expressions I use regularly.
📁 The project file with all of them is available for free.