To randomise the position apply an expression to the position property using the random()
function. This takes two parameters, the minimum and the maximum, and returns a random number between the two. Normally it returns a different number every time the frame gets rendered, which is not what we want, so we need to 'seed' it with a value and set it to timeless with the seedRandom()
function. We also need to return a two dimensional result because we need an x and y coordinate.
Putting that together:
seedRandom(index, timeless = true);
[random(12, 34), random(45, 67)]
Where 12, 34, 45, 67 are the values for the left, right, top and bottom minimum and maximums. Hard coding them is annoying if you want to be able to change the values later, so we'll set up a better system.
Add a null to the comp and apply the slider effect to it (effects>expression controls>slider) name the slider "left", then duplicate to make 3 more, called right, bottom and top. Make sure they're all visible in your timeline.
Now, in your layer's position expression, at the start type
let left =
Then grab the expression pick-whip and drag it to the left slider. It will auto-fill something like
let left = thisComp.layer("null 1").effect("left")("slider")
I'm on my phone so I can't remember if this is exactly right, but as long as you select the slider with your pick whip you're golden. Add a semicolon at the end of the line because that's how we roll in JavaScript.
Now repeat, changing left to right, bottom, and top, and pick-whipping the appropriate slider each time. The word left
here and the words right
, bottom
, top
are variables (we could have called them anything, like fee, fie, foe, fum, but you want your code to be readable). We'll use those variables instead of the hard coded values.
One last detail. Random is good, but it returns a random number that is evenly distributed between the minimum and maximum, you probably want something that clusters toward the middle, so that the leaves are denser near the branch. The gaussRandom()
function does that, so swap it for random.
Now we have:
let left = thisComp.layer("null 1").effect("left")("slider");
let right = thisComp.layer("null 1").effect("right")("slider");
let top = thisComp.layer("null 1").effect("top")("slider");
let bottom = thisComp.layer("null 1").effect("bottom")("slider");
seedRandom(index, timeless = true);
[gaussRandom(left, right), gaussRandom(top, bottom)];
Copy this expression to all your leaf layers and you'll have a cloud of leaves the size and position of which is controlled by your sliders. It's a DIY particle system.
To make the animation offset, apply the time remap effect to the layer, then use another expression. In this we generate a timeless random number between 0 and the length of the layer, and add that to the time remap value. To loop it back to the beginning at the end, we use the modulus operator ٪
, which returns the remainder of the first number divided by the second. Apply this to the time remap property:
seedRandom(index, timeless = true);
let myDuration = thisLayer.outPoint - thisLayer.inPoint;
(value + random(myDuration)) % myDuration;
In the seedRandom()
function you'll notice we're using index
as the first parameter. index
is the index of the layer, so for each different layer it returns a unique 'seed' for the random()
function, like spinning the roulette wheel each time. Also note that if you only give random()
one parameter it assumes that you want random numbers in the range 0 to that number.