Expressions and Tips
azerty AFX keyboard shortcuts
Loop animation before and after first and last keyframes
Should work with mask keyframes too, as opposed to loopOut/loopIn
Keep in mind that just like the normal loopOut, the last keyframe will always be replaced by the value of the first one, so you should have a sacrificial keyframe. Tried to have a one-liner but haven't wrapped my head around it quite fully
var offset = time<key(1).time?key(numKeys).time:key(1).time; valueAtTime( (time - offset ) % ( key(numKeys).time - key(1).time ) + offset );
Display current layer name
screenshot tbd this is pretty specific
pct =' ░▒▓█'; startIndex = 1;//what layer do I start with ? or use thisComp.layer('Null 1').index; lastCompIndex = thisComp.numLayers; outputText = ""; for(i=startIndex+1;i<=lastCompIndex;i++){ L = thisComp.layer(i); inP = L.inPoint; outP = L.outPoint; if(time >= inP && time < outP){ curT = time - inP; maxT = outP - inP; per = curT/maxT; outputText += pct.substr(Math.floor(per*4),1) + ' '; //comment out if you dont want visual progress outputText += L.source.name + '\n'; } } outputText;
Simple one liner if you put a text object above each layer (you have to do the in/out yourself)
thisComp.layer(thisLayer.index+1).source.name
Spread items along a path
Change path to fit your need, apply expresson to the position of your item layer, duplicate and you're set
// pointonpath uses a range from 0..1 to grab a position so let's figure our where we are // by counting the number of layers in the comp (and omitting a 'paths' layer at the bottom of the comp) // [0,1] [0,.5,1] [0,.333...,.666...,1] [0,.25,.5,.75,1] etc var percentpos = ( thisLayer.index - 1 ) / (thisComp.numLayers - 2) // prevents a divide by 0 error if there is only one object halfway through the path percentpos = isNaN(percentpos)? 0.5 : percentpos //grab path layer and path ugh, 'path' var pathLayer = thisComp.layer("path") var path = pathLayer.content("Shape 2").content("Path 1").path //grab position on path and use toComp to place it in the right spot var pos = path.pointOnPath( percentpos ) pathLayer.toComp(pos)
Retime (varispeed) any value
Allows time remapping of animation without having to time remap (and precomp) using valueAtTime and a slider
Add a slider control that you call 'speed', and then add this expression to remap it according to the animation as seen in the video above
speed = effect("speed")("Slider"); //slider varies between 0 and 1, allows precise slow ups and downs in a single slider p = thisProperty; firstT = p.key(1).time; lastT = p.key(p.numKeys).time; p = p.valueAtTime(speed*(lastT-firstT)+firstT)
Padded timer text
t = effect("Slider Control")("Slider"); sign = (t<0)?'-':''; t = Math.abs(t); s = t%60; m = Math.floor(t/60)%60; h = Math.floor(t/ (60*60)); s = (s<10)?'0'+s:s; // pads m = (m<10)?'0'+m:m; sign+h+':'+m+':'+s;
Rand characters
chars = "GATC"; textValue = ""; for(i=0;i<100;i++){ randVar = random() * chars.length; characterVar = chars.charAt(randVar); textValue = textValue + characterVar; } textValue;
Current Keyframe Index
//gobelins a = timeRemap; nk = a.nearestKey(time); curframe = 0; if(nk.time > time){ curframe = nk.index-1; }else{ curframe = nk.index; } curframe*thisComp.frameDuration;
a = position; //or whatever animated property nk = a.nearestKey(time); if(nk.time > time){ nk.index-1; }else{ nk.index; }
sample image pr les gobz
a = sampleImage([thisComp.width/2,thisComp.height/2], [thisComp.width/2,thisComp.height/2], postEffect = true, t = time); a[0]+a[1]+a[2]+a[3]; ////bake v = effect("s")("Curseur")-effect("s")("Curseur").valueAtTime(time-1/25)==0?0:1 //////bake? v = effect("hold")("Curseur"); a = 0; for(i=0;i<=time*25;i++){ if(v.valueAtTime(i/25)==1){ a = i/25; } } a;
spread thingy
p = thisComp.layer("Null 1").transform.position; delta = transform.position - p; amplitude = thisComp.layer("Null 1").effect("amplitude")("Slider"); reach = thisComp.layer("Null 1").effect("reach")("Slider"); exponent = thisComp.layer("Null 1").effect("exponent")("Slider") length = (length(delta)); if(length>0){ transform.position += normalize( delta ) * ( reach / Math.pow(length, exponent) ) * amplitude; }else{ transform.position = [-2000,0] }
Sprites
Duplicate layers by hand, add CtrlNul, offsetLeftRight, offsetDepth, spread sliders
//POSITION seedRandom(index,true) ctrl = thisComp.layer("CtrlNul"); dist = ctrl.effect("dist")("Slider"); offset = [ctrl.effect("offsetLeftRight")("Slider"),0,ctrl.effect("offsetDepth")("Slider")]; depthjitter = ctrl.effect("depthjitter")("Slider"); depthmult = ctrl.effect("depthmult")("Slider"); spread = ctrl.effect("spread")("Slider"); dist = dist+random()*spread; transform.position+[(index%2)?-dist:dist,0,depthmult*index+depthjitter*random()]+offset //ORIENTATION lookAt(transform.position,thisComp.layer("Camera 1").transform.position)
Write on effect
fps = 1/thisComp.frameDuration; cursorSpeed = 3; text.sourceText.slice(0,time*fps)+((Math.floor(time*cursorSpeed)%2)?"|":" ");
Unscramble wip
wordspeed = time/1; //or a slider, or whatever letterspeed = time*2; txt = text.sourceText; txtVar = ""; chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; splitxt = txt.split("\r"); maxLines = Math.min(splitxt.length-1, Math.floor(wordspeed)); for(i=0;i<=maxLines;i++){ txtVar += (i>0)?splitxt[i-1]+"\r":""; len = splitxt[i].length; if(i == maxLines){ for(j=0;j<=len-1;j++){ txtVar += (j/len>=wordspeed-Math.floor(wordspeed))?chars.charAt(random()*chars.length):splitxt[i].charAt(j); } } } txtVar ;
Poor man's padding
//for lack of a cleaner version, up to 4 digits a = time*25; a=(a<10)?"000"+a:((a<100)?"00"+a:((a<1000)?"0"+a:a));
2d lookat
LookAt = "ball" offset = 0 diffx = position[0] - this_comp.layer(LookAt).position[0]; diffy = position[1] - this_comp.layer(LookAt).position[1]; if (diffx == 0) { diffx = 1 } sign = 1 + (-1 * (diffx / Math.abs(diffx))) * 90; radians_to_degrees(Math.atan(diffy/diffx)) + sign + offset
//with parenting lookAt = "a"; L = thisComp.layer(lookAt); p = L.toComp(L.anchorPoint); d = thisLayer.toComp(anchorPoint) - p d[0] = (d[0]==0)?1:d[0]; rotation + radians_to_degrees(Math.atan(d[1]/d[0])) - 90*d[0]/ Math.abs(d[0])
Pixilation (slow footage)
numImages = 15; fps = 1/thisComp.frameDuration; framesToWait = 3;Math.floor(time*fps/framesToWait%numImages)/fps;
Text scroller (DOS!)
//add your text, three slider control effects and rename them 'line width', 'line', 'line animation' //then this expression on the source text charlen = Math.ceil(Math.abs(Math. round(effect("line width")("Slider"),0))); //20 numlines = Math.ceil(Math.abs(Math. round(effect("lines")("Slider"),0))); //5 step = Math.ceil(Math.abs(Math. round(effect("line animation")("Slider"),0))); txt = text.sourceText; splitxt = txt.split("\r"); output = ""; for(i=step;i<numlines+step;i++){ output += (i > splitxt.length - numlines)?".\r":splitxt[i].substring(0,charlen)+"\r"; } output;
//single line src = text.sourceText; len = src.length; scroll = time*25; src.slice(scroll%len)+src.slice(0,scroll%len)
/////////////
charlen =200; numlines = 15; step = time/thisComp.frameDuration; txt = text.sourceText; splitxt = txt.split("\r"); output = ""; for(i=step;i<(step+numlines);i++){ output += (splitxt.length<=i)?"\r":splitxt[i-1].substring(0,charlen)+"\r"; } output;
Open two simultaneous After Effects
"C:\Program Files\Adobe\Adobe After Effects CS5\Support Files\AfterFX.exe" -m
Command-Line
@echo off "C:\Program Files\Adobe\Adobe After Effects CS5\Support Files\aerender.exe" -mp -project "W:\