# Expressions & Snippets

## Transformation

<figure><img src="https://2289002225-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-Lgx0HTP5iKvQQwXUStq%2Fuploads%2FhFuQJfxXHZlVZnCbubv5%2FGB_Transform_Drift.gif?alt=media&#x26;token=6ff30130-038c-4e9e-b17d-68d0b38ea5a9" alt=""><figcaption></figcaption></figure>

### **Constant Value Drift and Motion**

#### 1. Linear Value Drift Over Time

```javascript
value + time * 50;
```

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

```javascript
value + [0, time * 5];
```

**3. Constant Horizontal Motion From Layer's Start Point**

<pre class="language-javascript"><code class="lang-javascript"><strong>offset = (time - inPoint) * -10;
</strong><strong>x = position[0] + offset;
</strong>y = position[1];
[x, y]
</code></pre>

### Align to X-axis or Y-axis

### X-Axis

<figure><img src="https://2289002225-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-Lgx0HTP5iKvQQwXUStq%2Fuploads%2Fm7ExcPbfAx1w887sGjYR%2Fimage.png?alt=media&#x26;token=47a524f2-3194-4f63-bb6f-9c425b79e56f" alt=""><figcaption><p>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.</p></figcaption></figure>

```javascript
var xOffset = 350;
var prevLayerX = thisComp.layer(index - 1).transform.position[0];
[xOffset + prevLayerX, value[1]];

```

### Y-Axis&#x20;

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

```

### Changing anchor point

```javascript
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

![A series of duplicated layers with random position values](https://2289002225-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Lgx0HTP5iKvQQwXUStq%2F-LvuPT8KPpZj0WUtKE0E%2F-LvuSO0lKmXxPkXip0IV%2F%20random_position.gif?alt=media\&token=b5dd55ec-a6a7-4d8e-8555-1371b0d64440)

```javascript
// 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.

```javascript
// 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&#x20;

{% tabs %}
{% tab title="Both" %}

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

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

scaleFactor;
```

{% endtab %}

{% tab title="uniform" %}

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

arr*ratio;
```

{% endtab %}
{% endtabs %}

**Implementation**

* [Scaling Radial Grid Expression · After Effects Tutorial · Master study: José Peña's "Creativity"](https://youtu.be/8BeI1qXzysU?t=122)

## Rotation

### [Aim constraint](https://creativecow.net/forums/thread/aim-constraint/) by Kevin Camp / Dan Ebberts

{% tabs %}
{% tab title="no parent" %}

```javascript
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
```

{% endtab %}

{% tab title="w/ parent" %}

```javascript
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
```

{% endtab %}

{% tab title="3D layers" %}

```
target = thisComp.layer("Null 1");// set this to the layer to aim at
lookAt( position, target.position )
```

{% endtab %}
{% endtabs %}

### [Retrieving auto-orientation rotation value](https://forums.creativecow.net/docs/forums/post.php?forumid=227\&postid=15409\&univpostid=15409\&pview=t)

```javascript
L = thisComp.layer("Null 1");
v = L.toWorldVec([1,0]);
radiansToDegrees(Math.atan2(v[1],v[0]))
```

### Auto-orient along path by [Videolancer](https://videolancer.net/expressions/)

```javascript
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

```javascript
value – parent.transform.rotation
```

## Opacity ✅

### Flickering / Strobe

![](https://2289002225-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Lgx0HTP5iKvQQwXUStq%2F-LvzsWJXFy3Waxu5GCzl%2F-Lvzv6zr3sH_kO9D4HI-%2Fflicker_Ebbert.gif?alt=media\&token=3c196e64-b5bf-48d5-9fc7-5806f3a160f6)

```javascript
// 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&#x20;

![](https://2289002225-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Lgx0HTP5iKvQQwXUStq%2F-LxgJHXu9wSt3wYE_ycC%2F-LxgTeeafXFWIXSvUAVz%2FrandomFade.gif?alt=media\&token=6fc0e18b-3610-4f23-a238-7438244d1583)

```javascript
// 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&#x20;

![](https://2289002225-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Lgx0HTP5iKvQQwXUStq%2F-LxgJHXu9wSt3wYE_ycC%2F-LxgTee_fD3Lkg-RBd8A%2FrandomFade_withFlicker.gif?alt=media\&token=5d4918ad-c03d-4552-8e68-e82c7b103402)

```javascript
// 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

![](https://2289002225-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Lgx0HTP5iKvQQwXUStq%2F-LvziloUSPc0AtBd6GcO%2F-LvzqIqZjkIfnahiz4Xp%2Fflicker_rand_sin.gif?alt=media\&token=e50a65cc-7eac-499e-b887-d8b56d35e3b4)

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

![](https://2289002225-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Lgx0HTP5iKvQQwXUStq%2F-LvziloUSPc0AtBd6GcO%2F-LvzqOfKOBy4vOe8vqGz%2Fflicker_rand_sinIndex.gif?alt=media\&token=f95e8445-915c-4402-be3b-8e267e48afc9)

```javascript
// '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

![](https://2289002225-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Lgx0HTP5iKvQQwXUStq%2F-LvuPT8KPpZj0WUtKE0E%2F-LvuSGW8ej9Hcu5gPtMv%2Frandom_opacity_turnon.gif?alt=media\&token=6857dd8b-dc18-4b3d-815c-86fafe4ae510)

```javascript
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&#x20;

![](https://2289002225-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Lgx0HTP5iKvQQwXUStq%2F-LvuPT8KPpZj0WUtKE0E%2F-LvuSL9ktGztg6U8qnuQ%2Frand_opacity_fadeon.gif?alt=media\&token=1f13691d-1f63-4175-81a9-9a25df3f3074)

{% tabs %}
{% tab title="v1" %}

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

linear(time, 0+delay,t+delay,0,100)
```

{% endtab %}

{% tab title="v2" %}

```javascript
//VARIABLES
fadeDuration = 1;
maxDelay = .5

//SETUP
seedRandom(index,true);
delay = random(maxDelay);
t = time -(inPoint + delay);

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

{% endtab %}
{% endtabs %}

### Distance-based opacity fade by Animoplex

```javascript
// 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

<figure><img src="https://2289002225-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-Lgx0HTP5iKvQQwXUStq%2Fuploads%2FMDC4bpIhV1QnCuqClwCf%2FGB_Transform_Opacity_CompVec.gif?alt=media&#x26;token=1b356629-f551-47aa-9288-bfd1bec5e30d" alt=""><figcaption></figcaption></figure>

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

## Colour

### [Hexcode from text to color](https://forums.creativecow.net/docs/forums/post.php?forumid=227\&postid=36789\&univpostid=36789\&pview=t)

```javascript
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

```javascript
// 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

### [Smoothing rotation of auto-orient along path](https://creativecow.net/forums/thread/smoothing-rotation-of-auto-orient-along-path/)

{% tabs %}
{% tab title="x-rot" %}

```javascript
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
```

{% endtab %}

{% tab title="y-rot" %}

```javascript
//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)
```

{% endtab %}
{% endtabs %}

## Motion

### Wiggle

![](https://2289002225-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Lgx0HTP5iKvQQwXUStq%2F-LxgV92bROKfqmwnVREA%2F-LxgwCQvpQ2zgLp0L3b-%2Fwiggle_all.gif?alt=media\&token=87d7aa30-7668-4151-9236-50d031dd547a)

```javascript
// 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);
```

* [Looping wiggle](https://www.motionscript.com/design-guide/looping-wiggle.html)

### Inertial Bounce / Overshoot

```javascript
// 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

```javascript
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&#x20;

![](https://2289002225-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Lgx0HTP5iKvQQwXUStq%2F-Lvf0ZKmdr-VLNU20ouZ%2F-LvfBiUXsAJ1IE2haa_y%2Fcarousel%20continuous.gif?alt=media\&token=05400a42-9680-482b-9ed8-1f0c894b31c7)

```javascript
/*  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

![](https://2289002225-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Lgx0HTP5iKvQQwXUStq%2F-Lvf0ZKmdr-VLNU20ouZ%2F-LvfB_ueezf9KXCBgUob%2Fcarousel_opacity.gif?alt=media\&token=f792a8e0-11a7-4dd1-89c2-276e24097fa8)

```javascript
// 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

{% code title="" %}

```javascript
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)
```

{% endcode %}

## Responsive Systems / Setups

### Dynamic-sizing text box / lower-third (depreciated, [see new code](https://docs.nosleepcreative.com/after-effects/broken-reference))

```javascript
// 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

![](https://2289002225-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Lgx0HTP5iKvQQwXUStq%2F-Lvk7_44IV7Igwsfne13%2F-Lvk7fplz1EScrLfOht_%2FEXP_slider.gif?alt=media\&token=afce9255-04b4-4839-a96b-597c933f2855)

```javascript
v = transform.position[0] // x 
d = length(v,thisComp.width/2);
maxDist= 960;

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

## Time Remapping / Playback ✅

![](https://2289002225-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Lgx0HTP5iKvQQwXUStq%2F-Lvk7rHlKiW6zINR4eoW%2F-LvkAgiEDExUK4lfIkT6%2FEXP_Counter.gif?alt=media\&token=7d561cef-44f7-478f-94bb-7d834fcc2d3a)

### Random frame playback

```javascript
// 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

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

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

```javascript
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)

```javascript
//Apply this to a composition with a image sequence inside
seedRandom(0,true);
t= random(0,72);
framesToTime(t);
```

### Playback at every nth frames&#x20;

```javascript
n = 3 // frames
time*n
```

### Hold and play every nth frames \[[source](https://www.reddit.com/r/AfterEffects/comments/59h2v0/is_there_a_way_to_render_every_nth_frame_in_after/?utm_medium=android_app\&utm_source=share)]

```javascript
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&#x20;
3. Add markers to trigger animations
4. Learn more
   * [Animoplex tutorial](https://www.youtube.com/watch?v=B_3XS2-VWOM\&t=698s)

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

## Staggering animations&#x20;

![](https://2289002225-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Lgx0HTP5iKvQQwXUStq%2F-LvudBN38effVOEtRXJL%2F-Lvuf4jS4Nc5XQANBNQg%2FstaggerAnimation.gif?alt=media\&token=eaa361c0-8702-4b33-91f5-4652f81de275)

```javascript
// 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 ✅

![](https://2289002225-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Lgx0HTP5iKvQQwXUStq%2F-LvuczcXa9SSOOwcY2E8%2F-Lvud2TcyFlQGLkBX6FC%2Felig_radial_scale.gif?alt=media\&token=a03e271b-a41a-4e8b-97a3-47fef332ceb1)

{% tabs %}
{% tab title="nsc" %}

```javascript
// 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)
```

{% endtab %}

{% tab title="OF" %}

```javascript
//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]
```

{% endtab %}
{% endtabs %}

### Effector opacity fade on ✅

![](https://2289002225-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Lgx0HTP5iKvQQwXUStq%2F-LwnCBz03bS5HglFFxPY%2F-LwnI2-VTH1AOJCZ-3JC%2FvalueAtTime_HexTile_Effector_Opacity_demo.gif?alt=media\&token=b38382d1-85f7-4819-a874-b1a6125c8d4a)

{% tabs %}
{% tab title="nsc" %}

```javascript
//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)
```

{% endtab %}

{% tab title="OF" %}

```javascript


```

{% endtab %}
{% endtabs %}
