Skip to main content

 

 

What is an after effects expression?
An After Effect expression is a programming Javascript language code that you insert in

It makes animations and your life easy! It may seem scary if you are new, but trust me, they are so useful and will become your best friend the more you use them and understand them.

How to use an expression?

To use an expression, just ALT-CLICK on any parameter that has a stopwatch icon

After Effects Expressions

I’ve been using expressions more and more over the years and have collected loads of useful and time-saving hacks that help me in my projects, some of these expressions date back to 2006 but still are useful and relevant today. Most of these expressions I have found or made myself with the help of Dan Ebberts or the Creative Cow forum. I won’t be able to credit each expression as I have gathered these all in a Word Doc that I have been adding to for years.

I have split each expression up into sections.

Animation and Movement

Bounce and Overshoot
n = 0; if (numKeys > 0){ n = nearestKey(time).index;
if (key(n).time > time){ n--; } }
if (n == 0){ t = 0; }else{ t = time - key(n).time; }
if (n > 0){ v = velocityAtTime(key(n).time - thisComp.frameDuration/10); 
amp = 0.05; 
freq = 2.0; 
decay = 4.0; 
value + v*amp*Math.sin(freq*t*2*Math.PI)/Math.exp(decay*t); }else{ value; }
Bounce and Overshoot v2
amp = 0.05;
freq = 2.0;
decay = 4.0;

n = 0;
if (numKeys > 0){
n = nearestKey(time).index;
if (key(n).time > time){
n--;
}
}
if (n == 0){
t = 0;
}else{
t = time - key(n).time;
}

if (n > 0){
v = velocityAtTime(key(n).time - thisComp.frameDuration/10);

value + v*amp*Math.sin(freq*t*2*Math.PI)/Math.exp(decay*t);
}else{
value;
}
Flickers
wiggle(5,100)
wiggle(20,100)
random(0,100)
100*Math.sin(time*2)
100*Math.sin(time*5)
1000*Math.sin(time*5)
Math.abs(100*Math.sin(time*Math.PI*1))
Math.abs(Math.sin(time*6))*100
Constant Stroke when scaling
s = transform.scale[0]; 
scaleFactor = 100/s;
value*scaleFactor;
Scale delay from the layer above 5 frame
delayFrames = 5
delay = framesToTime(delayFrames);
thisComp.layer(index+1).transform.scale.valueAtTime(time-delay)
Rotation delay from the layer above
delayFrames = thisComp.layer("control").effect("delayvalue")("Slider")
delay = framesToTime(delayFrames);
thisComp.layer(index+1).transform.rotation.valueAtTime(time-delay)
Stare
//add to rotation

L1 = thisLayer
L2 = thisComp.layer("> 4")//targetlayer
p1 = L1.toWorld(L1.anchorPoint);
p2 = L2.toWorld(L2.anchorPoint);
delta = p2 - p1;
radiansToDegrees(Math.atan2(delta[1],delta[0]));
Random position 

in a random amount of time and pause in this position for a random amount of time

moveMin = .3; //minimum move time
moveMax = .7; //maximum move time

pauseMin = .1; // minimum pause time
pauseMax = .5; // maximum pause time

minVal = [0.1*thisComp.width, 0.1*thisComp.height];
maxVal = [0.9*thisComp.width, 0.9*thisComp.height];

seedRandom(index,true);  // set pre-run for endT
endT = - random(moveMax);

j = 0;
k = 0;
while ( time >= endT){
  j += 1;
  seedRandom(j,true);
  startT = endT;
  if (j%2){
    endT += random(moveMin,moveMax);
    k++;
  }else{
    endT += random(pauseMin,pauseMax);
  }
}
if (j%2){
  seedRandom(k,true);
  endVal = random(minVal,maxVal);
  seedRandom(k-1,true);
  startVal = random(minVal,maxVal);
  ease(time,startT,endT,startVal,endVal)
}else{
  seedRandom(k,true);
  random(minVal,maxVal)
}
Drifting text from layer InPoint
veloc = -10; //horizontal velocity (pixels per second) 
x = position[0] + (time - inPoint) *veloc; 
y = position[1]; 
[x,y]
Animate along y only
x = value[0];
y = time*-190;
[x,y]
Animate along x only
x = time*-190;
y = value[1];
[x,y]
Auto fade in and out Layer depending on layer in/out points

Great for lower thirds, no keyframes required – apply to layer’s opacity, the animation will start on the inPoint and end on the OutPoint

fadeDuration = 0.75;
fadeIn = easeIn(time,inPoint,inPoint + fadeDuration, 0, 100);
fadeOut = easeOut(time,outPoint - fadeDuration , outPoint,0,100);
fadeIn-fadeOut

Wiggles

Wiggle Y Only:
[value[0],wiggle(1,100)[1]]
Wiggle X Only:
[wiggle(5,30)[0],value[1]]
Wiggle X and Y separately:
[wiggle(5,30)[0],wiggle(1,100)[1]]
Jumpy Wiggle
//Jumpy Wiggle 1 (moves at a random FPS)
v=wiggle(5,50);
if(v < 50)v=0;
if(v > 50)v=100;
v
Jumpy Wiggle 2 is similar to 1, but works at a defined FPS so your “jump” will happen at a regular pace.
fps=5; 
amount=50; 
wiggle(fps,amount,octaves = 1, amp_mult = 0.5,(Math.round(time*fps))/fps);
Wiggle +ve only
var myWiggle = wiggle(5,100);
var delta = myWiggle - value;
value + Math.abs(delta)
Looping wiggle x
freq = 0.05;
amp = 35;
loopTime = 20; //LOOPTIME
t = time % loopTime;
wiggle1 = wiggle(freq, amp, 1, 0.5, t);
wiggle2 = wiggle(freq, amp, 1, 0.5, t - loopTime);

w = linear(t, 0,  loopTime, wiggle1, wiggle2);


[w[0],value[1]]
Stop wiggling it at time 4 seconds:
timeToStop = 4; 
if (time > timeToStop){ 
   value; 
}else{ 
   wiggle(3,25); 
}
start wiggling at time 2 seconds and stop wiggling it at time 4 seconds:
timeToStart = 2; 
timeToStop = 4; 
 
if ((time > timeToStart) && (time < timeToStop)){ 
   wiggle(3,25); 
}else{ 
   value; 
}
Jumpy wiggle
fps=5; //frequency
amount=25; //amplitude
wiggle(fps,amount,octaves = 1, amp_mult = 0.5,(Math.round(time*fps))/fps);
Wiggle expression create hold keyframes
f = 2;
a = 10;
posterizeTime(f);
wiggle(f, a);

Method of making Wiggle Paths be loopable is this: FOR SHAPE/TEXT LAYERS

– set wiggles per second to 0;

– expression for Temporal Phase:

wigglesPerSecond = 0.5;
loopTime = 20;
Math.cos(degreesToRadians(360*time/loopTime))*360*wigglesPerSecond + value;
Expression for Spatial Phase:
wigglesPerSecond =4;
loopTime = 20;
Math.sin(degreesToRadians(360*time/loopTime))*360*wigglesPerSecond + value;
Wiggles based on the value of a slider
s = effect("Slider Control")("Slider");
w = wiggle(0.2,10);
if (s <= 0) {0} else {w}

Workflow and clever things

3D layer invisible while facing backwards to the camera (use on Opacity):
if (toCompVec([0, 0, 1])[2] > 0 ) value else 0
Get the number of words in a text layer
myText = text.sourceText;
myText.split(" ").length
Get Source text and Style FOR AE2019+
var t = thisComp.layer("tool").text.sourceText
var fontSize = t.style.fontSize;
var leading = t.style.leading;
style = t.style;
styleA = style.setFontSize(fontSize);
styleB = styleA.setText(t);
styleC = styleB.setLeading(leading);
Use the number from a text layer in a slider
parseFloat(thisComp.layer("text").text.sourceText);
Always keep Anchor Point centred
tempx = thisLayer.sourceRectAtTime(time,false).width/2 + thisLayer.sourceRectAtTime(time,false).left;
tempy = thisLayer.sourceRectAtTime(time,false).height/2 + thisLayer.sourceRectAtTime(time,false).top;
[tempx,tempy]

Offset anchor down from boxTop using half the height of the box
[value[0], boxTop + boxHeight/2 ];
Link keyframe value to the slider
if (numKeys > 1){
  t1 = key(1).time;
  t2 = key(2).time;
  v1 = 0;
  v2 = effect("start")("Slider");
  linear(time,t1,t2,v1,v2);
}else
  value
Slider control keyframe
x2 = effect("Slider Control 1")("ADBE Slider Control-0001");
x = linear(time,key(1).time,key(2).time,key(1).value[0],x2);
[x,x]
Dynamically moves first 2 and last 2 keyframes to in and out point
if (time < (inPoint+outPoint)/2)
  valueAtTime(key(1).time+time-inPoint)
else
  valueAtTime(key(numKeys).time-(outPoint-time));
Offset keyframes with slider
s=effect("Slider Control")("Slider")*-1
t = time + s;
valueAtTime(t)
Scrolling keyframed text
xVal = value[0];
yVal = value[1];
lineHeight = 13.5; // This must be changed by hand!
yOffset = 0; //   This must be changed by hand!
newY = Math.ceil(yVal/lineHeight)*lineHeight;
[xVal, newY+yOffset]
Copy size and rescale from the layer above
thisComp.layer(index - 1).scale-[7,7]
Copy rotation from layer below and rotate + x
//x is a number
thisComp.layer(index+1).transform.rotation+x
Copy position from the layer above
thisComp.layer(index-1).position
Time delay from the layer above
thisComp.layer(index+1).transform.position.valueAtTime(time-.1)

Widgets – Clocks, Timmers, Random Code Gen

For making FUI’s and random text

Decode user-defined characters to reveal define a string

Apply to the source text of a text layer

choices = "10"; 
str = "Decode expression by Nawaz Alamgir"; 
tStart = 1; //time at which the animation starts 
tStop = 4; //time at which the animation stop 
cps = 20; // characters per second 

if (time < tStart){
    seed = Math.floor(time*cps); 
    seedRandom(seed,true); 
    s = "";
    for (i = 0; i < str.length; i++){ 
        idx1 = Math.floor(random(choices.length));
        s += choices[idx1]; 
    } 
}
else if (time >= tStart && time < tStop){
    seed = Math.floor(time*cps); 
    seedRandom(seed,true); 
    s = "";
    sRand = ""; 
    for (i = 0; i < str.length; i++){ 
        idx1 = Math.floor(random(choices.length));
        idx2 = Math.floor(linear(time,tStart,tStop,0,1)*str.length); 
        sRand += choices[idx1]; 
        s = str.substr(0,idx2) + sRand.substr(idx2,str.length); 
    } 
}else{ 
    s = str; 
} 
s
Random Hex

Apply to the source text of a text layer

holdFrames = 3;
seed = Math.floor(timeToFrames(time)/holdFrames);
seedRandom(seed,true);
n = random(4294967296);
s = n.toString(16).toLowerCase();
while (s.length < 8) s = "0" + s;
s
Random MAC address

Generates a unique MAC address for every text layer instance

seedRandom(index,true);
s = "";
for (i = 0; i < 6; i++){
  if (i > 0) s += "-";
  str = Math.round(random(255)).toString(16).toUpperCase();
  if (str.length < 2) str = "0"+str;
  s += str;
}
s
Random Animated User Defined Characters

Apply to the source text of a text layer

c = ['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','0','1','2','3','4','5','6','7','8','9'];
framesPerChange = 4;
seed = Math.floor(timeToFrames(time)/framesPerChange);
seedRandom(seed,true);
s = "";
spl = value.split("\r");
for (i = 0; i < spl.length; i++){
  for (j = 0; j < spl[i].length; j++){
    r = Math.floor(random(0, c.length));
    s += c[r];
  }
  if (i != spl.length-1) s += "\r";
}
s
Random Animated Letters on a single line

Apply to the source text of a text layer

numOfLetters = 25; //Modify me
useSpaces = true; //Modify me
changeEveryFrame = true; //Modify me

//Don't modify below this line

seedRandom(index, !changeEveryFrame)
//--
function genLetter( ) {
r = random(65, 90);//from a to z
return String.fromCharCode( r );
}
s = "";
for(i = 0; i < numOfLetters; i++)
{
s += genLetter();
if(useSpaces)
s += " ";
}
s
Random Alpha Numeric String

Apply to the source text of a text layer

numRows = 1;
numChars = 8
holdFrames = 3;

seed = Math.floor(time/(holdFrames*thisComp.frameDuration));
seedRandom(seed,true);

s = "";
j = 0;
while(j < numRows){
k = 0;
while (k < numChars){
c = Math.floor(random(65,91));
s += String.fromCharCode(c);
k += 1;
}
s += "r";
j += 1;
}
s
Clock

Apply to the source text of a text layer

rate = 1;
clockStart = 0;
function padZero(n){
  return (n < 10 ? "0" : "") + n;
} 
clockTime = clockStart + rate*(time - inPoint);
if (clockTime < 0){
  sign = "-";
  clockTime = -clockTime;
}else{
  sign = "";
}
 
t = Math.floor(clockTime);
hr = Math.floor(t/3600);
min = Math.floor((t%3600)/60);
sec = Math.floor(t%60);
ms = clockTime.toFixed(2).substr(-2);
sign + padZero(hr) + ":" + padZero(min) + ":" + padZero(sec) + "." + ms
Counter with leading zeros
val = effect("Slider Control")("Slider"); 
numDec = 0; // digits to right of decimal 
numDigit = 2; // digits to left of decimal 
if (val < 0) sign = "-" else sign = ""; s = Math.abs(val).toFixed(numDec); while (s.length < numDigit + numDec + 1) s = "0" + s; sign + s
Time Clock

Apply to the source text of a text layer

h=15;m=29;s=3;f=7;
f+=timeToFrames();
s+=Math.floor(f*thisComp.frameDuration);
m+=Math.floor(s/60);
h+=Math.floor(m/60);
f=f%(1/thisComp.frameDuration);
s=s%60;
m=m%60;
if(f<10) {f="0"+f}
if(s<10) {s="0"+s}
if(m<10) {m="0"+m}
if(h<10) {h="0"+h}
h+":"+m+":"+s
Countdown Clock

Apply to the source text of a text layer

h=11;m=59;s=59;f=99;
f-=timeToFrames(t = time + thisComp.displayStartTime, fps = 3.99 / thisComp.frameDuration, isDuration = false);
s+=Math.floor(f/99);
m+=Math.floor(s/60);
h+=Math.floor(m/60);
f=f%99;
s=s%60;
m=m%60;
if(f<0) {f=100+f}
if(f<10) {f="0"+f}
if(s<10) {s="0"+s}
if(m<10) {m="0"+m}
if(h<10) {h="0"+h}
h+":"+m+":"+s+":"+f
Counter with leading zeros

Apply to the source text of a text layer and make a slider

val = effect("Slider Control")("Slider"); 
numDec = 1; // digits to right of decimal 
numDigit = 1; // digits to left of decimal 
if (val < 0) {sign = "-"} else {sign = ""; s = Math.abs(val).toFixed(numDec); while (s.length < numDigit + numDec + 1) s = "0" + s; sign + s}
Counting numbers with comma

Apply to the source text of a text layer

startCount = 0;
endCount = 11689;
countDur = 1.2;
s = "" + Math.round(linear(time,0,countDur,startCount,endCount));

if (s.length > 3){
s.substr(0, s.length -3) + "," + s.substr(-3);
}else{
s
}

 

Author Nawaz Alamgir

More posts by Nawaz Alamgir

Leave a Reply