Advanced expressions

Comp

Maintain stroke width

// from campkeyframe
sf = transform.scale[0]/100; ov = value; nv = ov / sf
// for parented shapes
value / length(toComp([0,0]), toComp([0.7071,0.7071])) || 0.001;
// https://battleaxe.tumblr.com/post/101945073972/maintain-stroke-weight-expression

Autonomous agents

Auto-capture ball by Aaron Cobb

var ball = thisLayer;
var cup = thisComp.layer("Cup");
var captureDuration = .25; //time for ball to reach center of cup once capture beings
var captureRadius = 100; //radius around anchor point of cup at which ball will be captured.
var captureTime = thisComp.duration; //time at which capture begins, default to end of comp
var currentDistance;
for(t = 0; t < captureTime; t = t + thisComp.frameDuration) //loop through frames{
currentDistance = length(ball.toComp(ball.anchorPoint.valueAtTime(t), t), cup.toComp(cup.anchorPoint.valueAtTime(t), t));
if(currentDistance < captureRadius) captureTime = t; //if inside capture radius exit the loop
}
// execute
ease(time, captureTime, captureTime + captureDuration, value, cup.toComp(cup.anchorPoint.value));

Normalize width of layers

nominalValue/width100nominalValue/width*100
nominal = 100
offset = 900; // connect to slider control
threshold = 0;
//
swidth = thisLayer.sourceRectAtTime().width;
svalue = nominal/swidth; *
// conditional
if(swidth>threshold){
[svalue,svalue,svalue]*offset
}
logo=thisLayer.source.layer(thisLayer.source.numLayers);
sHeight=height/logo.height;
sWidth=width/logo.width;
s=Math.min(sHeight,sWidth);
value*s

Normalizing image/logo sizes based on sampling alpha

normalizedScale=value(nominalValue/width)normalizedScale = value*(nominalValue/width)
width
height
ratio
width
nominalWidth = 200;
leftEdge = 0;
for (i = 0; i <= width; i++){
temp = sampleImage([i,height/2],[0.5,height/2],true,time);
if (temp[3] > 0){
leftEdge = i;
break;
}
}
rightEdge = width-1;
for (i = width-1; i >= 0; i--){
temp = sampleImage([i,height/2],[0.5,height/2],true,time);
if (temp[3] > 0){
rightEdge = i;
break;
}
}
value*nominalWidth/(rightEdge-leftEdge+1)
// cacheCompareSamplesPerSecond 0
height
nominalHeight = 200;
topEdge = 0;
for (i = 0; i <= height; i++){
temp = sampleImage([width/2,i],[width/2,0.5],true,time);
if (temp[3] > 0){
topEdge = i;
break;
}
}
bottomEdge = height-1;
for (i = height-1; i >= 0; i--){
temp = sampleImage([width/2,i],[width/2,0.5],true,time);
if (temp[3] > 0){
bottomEdge = i;
break;
}
}
alphaheight = (bottomEdge-topEdge+1); // in pixels
value*nominalHeight/alphaheight*100/value[1]
ratio
// for logos that are symmetrical
//nominal values;
n1 = 200;
n2 = 400;
n3 = 800;
topEdge = 0;
for (i = 0; i <= height; i++){
temp = sampleImage([width/2,i],[width/2,0.5],true,time);
if (temp[3] > 0){
topEdge = i;
break;
}
}
leftEdge = 0;
for (i = 0; i <= width; i++){
temp = sampleImage([i,height/2],[0.5,height/2],true,time);
if (temp[3] > 0){
leftEdge = i;
break;
}
}
=
aRatio = leftEdge/topHeight;
if(aRatio<1.1){value*n1/leftEfge

Expressions comment to prevent calculations on every frame

https://aescripts.com/auto-crop/

Compounding ease() interpolation (source)

You can't control the influence directly, but you can compound the ease such as below.

if (numKeys > 1){
t1 = key(1).time;
t2 = key(2).time;
v1 = [0,540];
v2 = [1080,540];
t = easeOut(time,t1,t2,0,1); // using a normalized value to drive the 2nd ease
easeOut(t,0,1,v1,v2);
}else
value