NoSleepCreative Wiki
  • Welcome to NoSleepCreative
  • After Effects
    • Getting Started with Expressions
    • Expressions & Snippets
      • JSX Cheatsheet
      • Expression Troubleshooting
      • Utilities
      • Shape & Mask
      • Type & Text
    • Cookbook
      • Algorithmic
      • Random properties
      • Harmonic Motion
      • Staggering
      • Tessellation & Tiling
      • Type animators
      • Speed lines
      • Radial Array
      • Orb & Trails
      • Shading & Texturing
      • Responsive
      • Automation
      • Setup & Rigs
    • Getting started with Scripting
    • Scripting
      • Utilities
      • Master Properties
    • ScriptUI
  • Studio Ops
    • Tooling
    • Toolkitting
    • Knowledge Base
    • Naming Convention
    • DAM
  • Cinema 4D
    • Formulas
    • Python Cheat Sheet
      • For Artists
      • Maya Environment
      • Maya snippets
      • VSFX 705
    • Cookbook
  • Info
    • About
    • Portfolio
    • Course
    • YouTube
    • Gumroad
    • GitHub
  • Dev
    • archive
      • Webscraping
      • Google Sheets Formulas
      • SQL
      • Terminal
      • C++
      • Unreal Engine
      • Concert Visualization
      • Dome-projection
      • UI UX
      • Professional Etiquettes
      • Woes
      • How to get better
        • Portfolio / Showreel
        • Design with cooking
      • Media theories
        • Post Cinematic Affect
        • Marxism, Reproduction and Aura
        • Heuristics & Authorship
        • 02 Semiotics
        • 3 Process?
        • 05
        • 06 Technology & Mediation
        • Formalism
        • Simulation
        • The Gaze & Media Critique
        • Import
        • 10-12
      • Recommended books
        • 🔴Things I learned
      • Mac Superuser
        • Applescript
      • InDesign
      • Illustrator
      • Blender
      • Premiere Pro
      • Mathematics
        • Probability
        • Linear Algebra
      • Shader Dev
      • Getting Started with After Effects
        • Best Practices
        • Pimping up AE
        • Environment
      • Houdini
        • Cheatsheet
        • Cookbook
        • Techniques
        • Dynamic
        • Rendering & Lighting
        • Animation
        • Particles
        • Others
          • Modeling
          • Fluids - Pyro & Smoke
          • Rendering
      • REGEX
    • Sandbox
      • Nexrender
        • Terminology
        • Project Files Preparation
Powered by GitBook
On this page
  • Transformation
  • Constant Value Drift and Motion
  • Align to X-axis or Y-axis
  • X-Axis
  • Y-Axis
  • Changing anchor point
  • Random positioning XYZ
  • Scale
  • Maintain Scale When Parented
  • Rotation
  • Aim constraint by Kevin Camp / Dan Ebberts
  • Retrieving auto-orientation rotation value
  • Auto-orient along path by Videolancer
  • Ignore Parent Rotation
  • Opacity ✅
  • Flickering / Strobe
  • Random opacity wiggle
  • Random opacity wiggle with flicker
  • Random opacity with sin function
  • Random opacity turn on
  • Random opacity fade on
  • Distance-based opacity fade by Animoplex
  • Transparent backside of 3D layer
  • Colour
  • Hexcode from text to color
  • Random fill
  • Camera
  • Smoothing rotation of auto-orient along path
  • Motion
  • Wiggle
  • Inertial Bounce / Overshoot
  • Constant move in either x or y axis / Random walker
  • Carousel
  • 2D
  • 3D
  • Responsive Systems / Setups
  • Dynamic-sizing text box / lower-third (depreciated, see new code)
  • Slider with center fade on
  • Time Remapping / Playback ✅
  • Random frame playback
  • Random delayed/advanced layer playback
  • Play one frame at a time (without 'float time')
  • Random still frame (Good for spriting)
  • Playback at every nth frames
  • Hold and play every nth frames [source]
  • Triggering animations with marker
  • Staggering animations
  • Radial scale up staggering ✅
  • Effector opacity fade on ✅

Was this helpful?

  1. After Effects

Expressions & Snippets

Here are list of useful expressions I curated and written. This page is currently being sorted into the pages under Cookbook & JSX Cheatsheet

PreviousGetting Started with ExpressionsNextJSX Cheatsheet

Last updated 7 months ago

Was this helpful?

Transformation

Constant Value Drift and Motion

1. Linear Value Drift Over Time

value + time * 50;

2. Apply Value Drift to Array Element eg. Position Y

value + [0, time * 5];

3. Constant Horizontal Motion From Layer's Start Point

offset = (time - inPoint) * -10;
x = position[0] + offset;
y = position[1];
[x, y]

Align to X-axis or Y-axis

X-Axis

var xOffset = 350;

var prevLayerX = thisComp.layer(index - 1).transform.position[0];

[xOffset + prevLayerX, value[1]];

Y-Axis

var yOffset = 350;
var prevLayerY = thisComp.layer(index - 1).transform.position[1];
[value[0], yOffset + prevLayerY];

Changing anchor point

var s = sourceRectAtTime();

// Top left ↖
[s.left, s.top] // 

// Top center ↑
[s.left, s.top] + [s.width / 2, 0];

// Top right ↗
[s.left, s.top] + [s.width, 0];

// Center left ← 
[s.left, s.top] + [0, s.height / 2];

// Center
[s.left, s.top] + [s.width, s.height] / 2;

// Center right → 
[s.left, s.top] + [s.width, s.height / 2]

// Bottom left ↙

[s.left, s.top] + [0, s.height]

// Bottom center ↓ 
[s.left, s.top] + [s.width / 2, s.height]

//Bottom right ↘
[s.left, s.top] + [s.width, s.height]

Random positioning XYZ

// Seed for randomization
var seed = 20;

// Define the minimum values for randomization
var minX = 25;
var minY = 25;
var minZ = -1900; 

// Define the maximum values for randomization
var maxX = thisComp.width;
var maxY = thisComp.height;
var maxZ = 50;

// Set the random seed
seedRandom(seed, true);

// Generate random values within the defined ranges
var randomX = random(minX, maxX);
var randomY = random(minY, maxY);
var randomZ = random(minZ, maxZ);

// Create an array with the random values
[randomX, randomY, randomZ];

Alternatively, you can use array variables for a preferred and shorter expression.

// Seed for randomization
var seed = 20;

// Define the minimum and maximum values for randomization
var minValues = [25, 25, -1900]; 
var maxValues = [thisComp.width, thisComp.height, 50];

// Set the random seed
seedRandom(seed, true);

// Create an array with the random values
random(minValues,maxValues)

Scale

Maintain Scale When Parented

var scaleFactor = [];
var parentScale = parent.transform.scale.value;

for (var i = 0; i < parentScale.length; i++) {
    scaleFactor[i] = (value[i] * 100) / parentScale[i];
}

scaleFactor;
arr = value;
ps = parent.transform.scale.value;
ratio = 100/ ps[0];

arr*ratio;

Implementation

Rotation

target = thisComp.layer("Null 1"); // set this to the layer to aim at
p = position - target.position;
radiansToDegrees( Math.atan2( p[1], p[0] ) )- 90
target = thisComp.layer("controls"); // set this to the layer to aim at
p = thisLayer.toWorld(anchorPoint) - target.position;
radiansToDegrees(Math.atan2(p[1], p[0])) - 90
target = thisComp.layer("Null 1");// set this to the layer to aim at
lookAt( position, target.position )
L = thisComp.layer("Null 1");
v = L.toWorldVec([1,0]);
radiansToDegrees(Math.atan2(v[1],v[0]))
try{
cornerEase = 3;
p = transform.position;
t = Math.min(Math.max(time,p.key(1).time+.001),p.key(p.numKeys).time);
pre = position.valueAtTime(t-thisComp.frameDuration*cornerEase);
post = position.valueAtTime(t+thisComp.frameDuration*cornerEase);
delta = post-pre;
orient = radiansToDegrees(Math.atan2(delta[0],-delta[1]));
value+orient+180
}catch(err){value}

Ignore Parent Rotation

value – parent.transform.rotation

Opacity ✅

Flickering / Strobe

// VARIABLES
    minSeg = 1.5; //minimum interval (must be > 0) 
    maxSeg = 2.5; //maximum interval (must be > minSeg) 
    
    // flickering duration
    minFlicker = .5; //must be less than minSeg 
    maxFlicker = 1; // must be less than minSeg 
    flickerDur = random(minFlicker,maxFlicker);
    
    //initial conditions
    segEndTime = 0; 
    i = 1; 

// Continuous loop: create a fixed random segment value and add to segEndTime
while (time >= segEndTime){ 
    i += 1; 
    seedRandom(i,true); 
    segEndTime = segEndTime + random(minSeg,maxSeg); 
} 

// Switch back to use the current time as input to the random seed.
seedRandom(1,false); 

// As time > threshold, flicker
if (time > segEndTime - flickerDur){random(0,100) }else{ 100 }

// Source: http://www.motionscript.com/expressions-lab-ae65/swinging-light.html
// Also see: http://www.motionscript.com/mastering-expressions/random-3.html

Random opacity wiggle

// control = thisComp.layer("control"); // connect to null layer with sliders
freq = 1;
amp = 100;
octave = 1;
amp_mult = 3;

wiggle(freq, amp, octave, amp_mult, time)

Random opacity wiggle with flicker

// control = thisComp.layer("control"); // connect to null layer with sliders
freq = 1;
amp = 100;
octave = 1;
amp_mult = 3;

opacity = wiggle(freq, amp, octave, amp_mult, time)


// VARIABLES
minSeg = control.effect("minSeg")("Slider"); //minimum interval (must be > 0) 
maxSeg = control.effect("maxSeg")("Slider");; //maximum interval (must be > minSeg) 

// flickering duration
minFlicker = control.effect("minFlicker")("Slider");; //must be less than minSeg 
maxFlicker = control.effect("maxFlicker")("Slider");; // must be less than minSeg 
flickerDur = random(minFlicker, maxFlicker);

//initial conditions 
segStartTime = 0;
segEndTime = 0;
i = 1;

// Continuous loop: create a fixed random segment value and add to segEndTime
while (time >= segEndTime) {
    i += 1;
    seedRandom(i, true);
    segStartTime = segEndTime;
    segEndTime = segEndTime + random(minSeg, maxSeg);
}

// Switch back to use the current time as input to the random seed.
seedRandom(1, false);

// As time moves threshold, flicker
if (time > segEndTime - flickerDur) {
    random(0, 100)
} else {
    opacity
}

Random opacity with sin function

// Mass flickering
vel = 50;
seedRandom(0,true);
Math.sin(time*vel+random(index))*100;
// 'Wave flickering'
vel = 50;
seedRandom(0,true);
Math.sin(time*vel+index)*100;


// Combining 
bool = 1
;
vel = 50;

seedRandom(0,true);

wave=Math.sin(time*vel+index)*100;

rand =Math.sin(time*vel+random(index))*100;


bool==0 ? wave : rand;

Random opacity turn on

seed = 29;
threshold = linear(time,0,thisComp.duration,0,100); // or Connect to slider to animate switch on & off

seedRandom(seed,true);
randValue = random(0,90);

if(randValue < threshold){
    100;} else 0

Random opacity fade on

seed = 29;
seedRandom(seed,true);
delay = random(0,1);
t = framesToTime(20) // or usethisComp.duration

linear(time, 0+delay,t+delay,0,100)
//VARIABLES
fadeDuration = 1;

maxDelay = .5

//SETUP

seedRandom(index,true);

delay = random(maxDelay);

t = time -(inPoint + delay);


// EXECUTION
linear(t,0,fadeDuration,0,100);

Distance-based opacity fade by Animoplex

// Distance Based Opacity Fade
// Original: https://helpx.adobe.com/after-effects/using/expression-examples.html
// Full Tutorial: https://www.youtube.com/watch?v=I-Acdl_l9G0&t=14s

startFade = 500;
endFade = 3000;
try {
    C = thisComp.activeCamera.toWorld([0,0,0]);
} catch(err) {
    w = thisComp.width * thisComp.pixelAspect;
    z = (w / 2)/Math.tan(degreesToRadians(19.799));
    C = [0,0,-z];
}
P = toWorld(anchorPoint);
d = length(C, P);
linear(d, startFade, endFade, 100, 0)

Transparent backside of 3D layer

if (toCompVec([0, 0, 1])[2] > 0 ) value; else 0;

Colour

txt = thisComp.layer("Text").text.sourceText;
c = parseInt(txt,16);
r = c >> 16;
g = (c & 0x00ff00) >> 8;
b = c & 0xff;
[r,g,b,255]/255

Random fill

// Apply on Color Controls
seed = 20;
seedRandom(seed,true); // change true to 0 for constant change
random([0,0,0,1],[1,1,1,1])

Camera

f = 2; // number of frames before and after to average
v = [0,0];
for (i = -f; i <= f; i++){
v += position.velocityAtTime(i*thisComp.frameDuration + time);
}
v /= (f*2+1);
a = Math.atan2(v[1],v[0]);
radiansToDegrees(a)

// turn off auto-orient
//y-rotation for 3d layers

f = 2; // number of frames before and after to average
v = [0, 0, 0];
for (i = -f; i <= f; i++) {
    v += position.velocityAtTime(i * thisComp.frameDuration + time);
}
v /= (f * 2 + 1);
a = Math.atan2(v[0], v[2]);
radiansToDegrees(a)

Motion

Wiggle

// frequency by amplitude = how fast by how much
wiggle(20,30);

[value[0], wiggle(20,30)[1]] // wiggle y-axis only 


// Smooth wiggle — freq,amp,octave,amp_mult
wiggle(20,30,1,2,time)


// Jumpy Wiggle 1 (moves at a random FPS) Makes wiggle skip and hold rather than move fluidly.

v=wiggle(5,50);
if(v < 50)v=0;
if(v > 50)v=100;
v;

// Jumpy Wiggle 2 (moves at a defined FPS)
fps=5; //frequency
amount=50;  //amplitude
wiggle(fps,amount,octaves = 1, amp_mult = 0.5,(Math.round(time*fps))/fps);

Inertial Bounce / Overshoot

// Inertial Bounce (moves settle into place after bouncing around a little)
// // Source: https://forums.creativecow.net/docs/forums/post.php?forumid=227&postid=19145&univpostid=19145&pview=t
amp = .05;
freq = 4.0;
decay = 2.0; // springyness
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;
}

Constant move in either x or y axis / Random walker

WIP---
choice = Math.floor(random(0,2));
seedRandom(0,false);
stepx = random(0,50);
stepy = random(0,20);
if(choice ==0){
	value + [stepx,0];} else if( choice ==1){
	value +[0,stepy];}

Carousel

2D

3D

/*  There needs to be two layers named 'startCard' & 'endCard'
    This allows rotation value to dynamically change when layers are inserted or removed.
    All duplicates need to be placed within these two layers
*/

//anchor point
radius = 500
value+[0,0,radius]

// Y rotation

startIndex=thisComp.layer("startCard").index; 

endIndex = thisComp.layer("endCard").index;
numpt = startIndex-endIndex+1; // total number of layers


myIndex = index-startIndex;


angle = 360/numpt


myIndex*angle+

Linking layers' rotation with opacity

Using distance & vector position

// Make sure there is a camera 

//Opacity
startVal = 0;
endVal = 100;
fadeAngle = 180;

v = toCompVec([0,0,1]); // layer position to comp position in Z
d = length(toWorld(anchorPoint),thisComp.layer("Camera 1").toWorld([0,0,0]));
c = v[2]/d;
ease(c,Math.cos(degreesToRadians(fadeAngle)),1.0,startVal,endVal)

Using rotation

angle = transform.yRotation%360;
minAngle = 0;
maxAngle = 360;
mid = (maxAngle+minAngle)/2;
if (angle < mid)
  linear(angle,minAngle,mid,100,0)
else
  linear(angle,mid,maxAngle,0,100)

Responsive Systems / Setups

Dynamic-sizing text box / lower-third (depreciated, see new code)

// Create two text layers named "DATA1" & "DATA2"
// Variables
pad = 50;
xPad = 15;

yPad = 15;


seed = 1 // allow you to change between two text layers

// Making it work
if(seed==1){
	
    src = thisComp.layer("DATA1")
    }else {
		
        src = thisComp.layer("DATA2")
		
        }; 


box = src.sourceRectAtTime(time-src.inPoint); 

[box.width + pad + xPad, box.height+pad +yPad];

Slider with center fade on

v = transform.position[0] // x 

d = length(v,thisComp.width/2);

maxDist= 960;


ease(d,0,maxDist,100,0)

Time Remapping / Playback ✅

Random frame playback

// Source Dan Ebbert

fr = 12; // frame rate;

numFrames = 8;

seedRandom(index,true);

seg = Math.floor(time*fr);

f = Math.floor(random(numFrames));

for (i = 0; i < seg; i++)

  f = (f + Math.floor(random(1,numFrames)))%numFrames;

framesToTime(f);

Random delayed/advanced layer playback

seedRandom(index,true);
myDelay = random(1,10);
time + myDelay;

Play one frame at a time (without 'float time')

fps = 1;

x = framesToTime(Math.round(time*fps))
//There probably is a better way but I cannot figured it out right now.

Random still frame (Good for spriting)

//Apply this to a composition with a image sequence inside
seedRandom(0,true);

t= random(0,72);

framesToTime(t);

Playback at every nth frames

n = 3 // frames
time*n
n = 3;  // play every __ frames
m = 3; // hold each frame ___ times 

f= timeToFrames(timeRemap);

p=Math.floor(f/m);

framesToTime(p*n);

Triggering animations with marker

Workflow

  1. Create a preComp with all the different types of animation

  2. In the main Comp, put an expression on the time remapping of that preComp

  3. Add markers to trigger animations

  4. Learn more

//https://gist.github.com/animoplex/cecf1c64aec4f2733ecd0edbebf4786d

Staggering animations

// Copying animation of a layer, and start it at inPoint of layer
thisComp.layer(index+1).transform.position.valueAtTime(time-inPoint)

// Using delay
offset = 1;
thisComp.layer(index+1).transform.position.valueAtTime(time-offset)    

Radial scale up staggering ✅

// VARIABLES + SETUP

target = thisComp.layer("master").transform.scale; 

maxDist = 1000;

maxDelay = 1;


dst = length(transform.position,[thisComp.width/2,thisComp.height/2]);

delay = linear(dst,0,maxDist,0,maxDelay);



// EXECUTION

target.valueAtTime(time-delay)
//apply to scale
target = thisComp.layer("fade");
fade = target.effect("scale")(1);
delay = target.effect("delay")(1)*thisComp.frameDuration;
dist = length(thisLayer.toWorld(thisLayer.anchorPoint), target.toWorld(target.anchorPoint));
seed = seedRandom(15, true)
randomRange = target.effect("random")("Slider");
rand = (random(-randomRange, randomRange))*thisComp.frameDuration;
offset = delay/dist;
s = fade.valueAtTime(time - offset - rand);
[s,s]

Effector opacity fade on ✅

//Create a null named "EFFECTOR" 
//Add 2 Slider Control Effects renamed to "maxDist" and "delay"


// EXECUTE
target = thisComp.layer("EFFECTOR").transform
maxDist = thisComp.layer("EFFECTOR").effect("maxDist")("Slider");
maxDelay = thisComp.layer("EFFECTOR").effect("delay")("Slider");

dst = length(transform.position, target.position);
delay = linear(dst, 0, maxDist, 0, maxDelay);

// EXECUTION
target.opacity.valueAtTime(time - delay)

by Kevin Camp / Dan Ebberts

Auto-orient along path by

Hold and play every nth frames []

Scaling Radial Grid Expression · After Effects Tutorial · Master study: José Peña's "Creativity"
Aim constraint
Retrieving auto-orientation rotation value
Videolancer
Hexcode from text to color
Smoothing rotation of auto-orient along path
Looping wiggle
source
Animoplex tutorial
This expression references the X position of the layer above in the Composition panel and adds a fixed increment, resulting in a row of evenly spaced child layers.
A series of duplicated layers with random position values