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
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 }