Hey Klaus, it’s time to solve this, I’ve worked on some code for you, i left some comments so you can orient yourself, it turns the null’s proximity into a one-shot trigger for each shape. When the null crosses into the defined distance, the expression records that moment and starts a self-contained 0→100→0 animation for that shape. The animation keeps playing even if the null leaves immediately, and it won’t restart until the null exits the range and enters again later.
Good luck and lemme know if you apprecciate the help!
// Paste this on the property you want to animate (e.g. Glow Opacity or a Slider).
// Adjust rangeMin, animLen and nullName as needed.
var rangeMin = 100; // trigger distance in pixels
var animLen = 1.0; // animation length in seconds (how long the 0->100->0 plays)
var nullName = "Null 1"; // name of your null layer
var easeInOut = true; // use ease() for smooth curve (true) or linear (false)
var nl = thisComp.layer(nullName);
var frameDur = thisComp.frameDuration;
var maxBack = animLen + 0.5; // how far back to search for a trigger (seconds)
function distAt(t){
var pShape = thisLayer.toComp(thisLayer.anchorPoint);
var pNull = nl.toComp(nl.anchorPoint);
return length(pShape, pNull);
}
// find the most recent entrance (time when distance crossed from >range to <=range)
// search backward up to maxBack, stepping by one frame
function findLastEntrance(t){
var steps = Math.ceil(maxBack / frameDur);
for (var i = 0; i <= steps; i++){
var ts = t - i*frameDur;
if (ts <= 0) break;
var dNow = distAt(ts);
var dPrev = distAt(Math.max(0, ts - frameDur));
if (dNow <= rangeMin && dPrev > rangeMin){
// refine a bit with half-step binary search for a slightly more accurate entrance time
var a = Math.max(0, ts - frameDur);
var b = ts;
for (var k = 0; k < 6; k++){ // 6 iterations -> ~1/64 frame accuracy
var m = (a + b)/2;
if (distAt(m) <= rangeMin) b = m; else a = m;
}
return b;
}
}
return -1;
}
var t = time;
var lastEnter = findLastEntrance(t);
if (lastEnter < 0){
// no recent trigger within animLen+0.5s -> idle
0
} else {
var prog = (t - lastEnter) / animLen;
if (prog < 0 || prog > 1){
0
} else {
if (easeInOut){
// go 0 -> 100 -> 0 using a triangular eased curve
var val;
if (prog <= 0.5){
val = ease(prog*2, 0, 1, 0, 100); // first half 0->100
} else {
val = ease((prog-0.5)*2, 0, 1, 100, 0); // second half 100->0
}
val
} else {
var val;
if (prog <= 0.5){
val = linear(prog*2, 0, 1, 0, 100);
} else {
val = linear((prog-0.5)*2, 0, 1, 100, 0);
}
val
}
}
}