This has been a bit more difficult than i first imagined.
You need to create a control layer with 3 sliders: Duration, Forground layers, Layers numbers.
The expression takes one value from duration keyframes as the duration of the animation for each cycle. Ex: Duration has 3 keyframes:1,2,3. The first 3 cycles will have the duration of the animation 1,2 respectively 3. It does not matter where the keyframes are in time. After 3 cycles, the animation continues with the last duration for all the folowing cycles.
If no keyframe is present in Duration slider, it will take its value and create cycles with that.
You need to add this exression to the opacity of your layers:
layersNumber = thisComp.layer("Control Layer").effect("Layers Number")("Slider");
forGroundLayers = thisComp.layer("Control Layer").effect("Foreground Layers")("Slider");
dur = thisComp.layer("Control Layer").effect("Duration")("Slider");//Duration for the animation
function extractCycles(myDur){
cycleValues = [inPoint];
for (var i=1; i<=myDur.numKeys; i++){
cycleValues.push(cycleValues[i-1] + myDur.key(i).value * layersNumber);
}
if (myDur.numKeys == 0) var cycleValues = myDur.value;
return cycleValues;
}
cycleStarts = extractCycles(dur);
lastCycleEnd = cycleStarts[cycleStarts.length-1];
myIndex = index-1-forGroundLayers;
if (dur.numKeys>0){
if (time < lastCycleEnd){
//Check to see in which cycle we fit
var i = cycleStarts.length-1;
while(cycleStarts[i] > time && i!=0){
i--;
}
cycleLength = cycleStarts[i+1]-cycleStarts[i];
thisDuration = cycleLength/layersNumber;
(((time-cycleStarts[i]-myIndex*thisDuration) % cycleLength) <= thisDuration) ? 100 : 0;
}else{
//Continuously loops with the last duration
(((time-lastCycleEnd-myIndex*dur.key(dur.numKeys).value) % (dur.key(dur.numKeys).value*layersNumber)) <= dur.key(dur.numKeys).value) ? 100 : 0;
}
}else{
((time-inPoint-myIndex*dur) % (dur*layersNumber) <= dur) ? 100 : 0;
}
And here is the aep project
Andrei
My Envato portfolio.