Creative Communities of the World Forums

The peer to peer support community for media production professionals.

Activity Forums Adobe After Effects Expressions Using sliders to change time of opacity shifts

  • Using sliders to change time of opacity shifts

    Posted by Luke Mckinney on September 20, 2019 at 5:37 pm

    So I’m currently self learning expressions and a lot of what I’ve been able to pull off is by copy/pasting code and trying to modify it for my needs.
    I have a pretty complex problem and have achieved results good enough for this one project but would love to create a template so I could repeat this easier in the future.
    What is going on is I have 5 video layers. When triggered using a checkbox the top layer will shift from 100% opacity to 0%. The on and off times are determined with two sliders. I’m needing to change the “flicker” speed during the clip which is why I decided to build this all around sliders. I’ve built a ton of code into this thing and I’m really looking for 1 – a more elegant solution for this workflow and 2 – a code that won’t leave opacity gaps in the composition since the only way I could figure this out is by referencing previous frames which doesn’t always work when you shift the keyframes.
    I know I probably haven’t included enough information but any leads/help would be greatly appreciated.

    Also, a disclaimer, I’m not 100% sure that all of this code is correct or even what a couple parts of it do.

    //The code from the Main video layer named "PJ";
    A = thisComp.layer("Master Controller").effect("Cycle in Seconds")("Slider");
    B = thisComp.layer("Master Controller").effect("Frame Rate Adjusted")("Slider")*thisComp.frameDuration;

    ((time-inPoint)%A <= B) ? 100 : ((thisComp.layer("Master Controller").effect("On / Off")("Checkbox")-1)*-100);

    // This is the code from the video layers directly under "PJ";

    frameRate = thisComp.layer("Master Controller").effect("Frame Rate")("Slider");
    delay = (frameRate*(index-1))*thisComp.frameDuration;

    thisComp.layer("PJ").transform.opacity.valueAtTime(time-delay);

    //This is the code from the main slider driving the rest of the expressions on layer "Master Controller";

    cycleRate = effect("Cycle in Seconds")("Slider");
    frameRate = effect("Frame Rate")("Slider");
    frameDur = frameRate * thisComp.frameDuration;
    nearKey = effect("Frame Rate")("Slider").nearestKey(time).index;
    lastKey = (frameRate.key(nearKey).time>time) ? ((nearKey>1) ? nearKey-1 : nearKey) : nearKey;
    prevKey = frameRate.key(lastKey).index-1;
    FG = effect("ForeGround Layers")("Slider");
    if
    ((frameRate.key(lastKey).index == frameRate.key(nearKey).index) && (time - frameRate.key(lastKey).time <= cycleRate) && (frameRate.key(prevKey).value > frameRate.key(lastKey).value)) //if lowering frame rate
    {
    frameRate.value;
    thisComp.layer("PJ").transform.opacity.valueAtTime(time+(index-FG)) = 100;
    thisComp.layer("Mike").transform.opacity.valueAtTime(time+(index-FG)) = 100;
    thisComp.layer("Cody").transform.opacity.valueAtTime(time+(index-FG)) = 100;
    thisComp.layer("Matt").transform.opacity.valueAtTime(time+(index-FG)) = 100;
    thisComp.layer("Rob").transform.opacity.valueAtTime(time+(index-FG)) = 100;
    }
    else if
    ((frameRate.key(nearKey).time - time <= cycleRate) && (frameRate.key(nearKey).value < frameRate.key(lastKey).value)) // if raising frame rate
    {
    frameRate.value;

    thisComp.layer("PJ").transform.opacity.valueAtTime(time) = 100;
    thisComp.layer("Mike").transform.opacity.valueAtTime(time+(index-FG)) = 100;
    thisComp.layer("Cody").transform.opacity.valueAtTime(time+(index-FG)) = 100;
    thisComp.layer("Matt").transform.opacity.valueAtTime(time+(index-FG)) = 100;
    thisComp.layer("Rob").transform.opacity.valueAtTime(time+(index-FG)) = 100;
    }
    else {
    frameRate.value;
    }

    // There's a slider for ForeGround elements ( a couple scenes are green screened);
    if (thisComp.layer("PJ").index == 1)
    {
    0;
    }
    else
    {
    thisComp.layer("PJ").index - 1;
    }
    Math.floor(value);

    //and this is the cycle expression that auto populates this slider based off of the comp;
    (effect("Frame Rate")("Slider")*(index-1-effect("ForeGround Layers")("Slider")))*thisComp.frameDuration;

    Luke Mckinney replied 6 years, 11 months ago 2 Members · 7 Replies
  • 7 Replies
  • Andrei Popa

    September 21, 2019 at 7:42 am

    Is this like a loading animation that accelerates or something?

    What i understand you want to do:
    Layer one becomes invisible when meets the checkbox. Other 4 layers follow at a given delay(your frameRate). You want to modify this framerate over the time? You also want to modify the cycle time to fit the new “frameRate”?

    Am I correct in my assuptions?

    Andrei
    My Envato portfolio.

  • Luke Mckinney

    September 21, 2019 at 5:15 pm

    Your assumptions seem to be correct! I’ll include some more info here to try to help clarify everything.

    This is creating a replacement animation effect using video rather than shooting stills frame by frame. The effect is an allegory for the character’s emotional state so we need to be able to speed up and slow down the speed of the effect, which is why I’m trying to keyframe the frame rate slider.

    Ideally, the keyframes would auto-move to the end of a cycle before changing to the new frameRate.

    Thanks for trying to decipher both my code and my concept!!!

    13736_screenshot20190921at12.03.01pm.png.zip

    13735_screenshot20190921at12.04.09pm.png.zip

  • Andrei Popa

    September 21, 2019 at 8:55 pm

    Hey. I’m not at the office until monday morning CET and I don’t have After Effects at home.
    I’ll try to make something work then and reply, in case anyone else does not do it before me 😀

    Andrei
    My Envato portfolio.

  • Luke Mckinney

    September 22, 2019 at 3:23 am

    Thank you!

  • Andrei Popa

    September 23, 2019 at 8:26 am

    This has been way harder than i first imagined ????

    You need 3 sliders on your control layer: Forground layers, Duration and Number of layers.
    Add this expression to opacity to each of the 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;
    }

    Andrei
    My Envato portfolio.

  • Andrei Popa

    September 23, 2019 at 8:32 am

    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.

  • Luke Mckinney

    September 24, 2019 at 2:41 pm

    It works a lot more cleanly than what I came up with!!!! Thank you so much!!!

    I can’t find anything in the expressions manual I downloaded on cycles or variables. Do you know of any good resources for learning about this. Just trying to avoid having to bother you for help again. Thanks!

We use anonymous cookies to give you the best experience we can.
Our Privacy policy | GDPR Policy