Creative Communities of the World Forums

The peer to peer support community for media production professionals.

Activity Forums Adobe After Effects Expressions Delay textIndex based on slider/position control with expression selectors

  • Delay textIndex based on slider/position control with expression selectors

    Posted by Julian Chojnacki on January 17, 2023 at 1:52 am

    Hi there! I want to add a delay between each textIndex to the following code on a position animator: 

    const flip = effect("Flip")("Checkbox");

    const stggr = effect("Stagger")("Slider");


    const range = textTotal/2;

    const offst = Math.round(textTotal/2 - textIndex);

    const rO = offst/range;


    const mod = Math.cos(Math.PI*2 + rO*2) + 1;

    let sel = linear(textIndex, 1, textTotal, -100, 100);

    sel = textIndex > textTotal/2 && flip == 1 ? -sel : sel;


    if(stggr <= 0) {

    easeL = sel * mod

    v = ease(stggr, -100, 0, easeL, sel);

    } else if(stggr >= 0) {

    easeH = sel / mod/2

    v = ease(stggr, 0, 100, sel, easeH);

    }

    const sldr = effect("Matte 2")("Slider")

    const pos = effect("Position")("3D Point");

    It is basically a linear wave with an easing modulator, that is flipped in the center if the checkbox is ticked. Ideally, I’d like to be able to keyframe a slider or 3D point control, and add valueAtTime to the textIndex, while preserving the curve & flip. I’ve been experimenting for hours, but couldn’t find the solution. Maybe it’s simpler than I think…

    Any hints would be great🙂

    Julian Chojnacki replied 3 years, 2 months ago 3 Members · 15 Replies
  • 15 Replies
  • Julian Chojnacki

    January 21, 2023 at 5:05 pm

    Anyone?

  • Julian Chojnacki

    January 21, 2023 at 5:36 pm

    For visual reference, here’s what I’m trying to add a slight word delay to:

  • Dan Ebberts

    January 21, 2023 at 5:57 pm

    I’m not sure exactly what you’re after, but if you wanted to delay the effect of an animated stagger slider based on textIndex, you would stick something like this in there (not tested):

    delay = .1;
    myDelay = delay*(textIndex-1);
    stggr = effect("Stagger")("Slider").valueAtTime(time-myDelay);
  • Julian Chojnacki

    January 21, 2023 at 6:27 pm

    Hi Dan! Thanks for getting back. I am aware of this concept, but I’m guessing it’s not as simple in my case, as I want to preserve everything in my code, but only add a slight delay to each word when I animate the animator’s position. (Or if that doesn’t work, a slider)

    I hope the video I posted above shines a light on what I’m after.

    Here’s another example:
    https://youtu.be/ce3h46mp4Q4?t=89

    Some contents or functionalities here are not available due to your cookie preferences!

    This happens because the functionality/content marked as “Google Youtube” uses cookies that you choosed to keep disabled. In order to view this content or use this functionality, please enable cookies: click here to open your cookie preferences.

  • Dan Ebberts

    January 21, 2023 at 7:14 pm

    I wish I could help, but I don’t get it. Maybe somebody else will…

  • Julian Chojnacki

    January 21, 2023 at 7:21 pm

    No worries Dan, thanks for your effort🙂

  • Filip Vandueren

    January 22, 2023 at 2:58 pm

    Something like this would work:

    const flip = effect("Flip")("Checkbox");
    const stggr = effect("Stagger")("Slider");
    const range = textTotal/2;
    const offst = Math.round(textTotal/2 - textIndex);
    const rO = offst/range;
    const mod = Math.cos(Math.PI*2 + rO*2) + 1;
    let sel = linear(textIndex, 1, textTotal, -100, 100);
    sel = textIndex > textTotal/2 && flip == 1 ? -sel : sel;
    if(stggr <= 0) {
    easeL = sel * mod
    v = ease(stggr, -100, 0, easeL, sel);
    } else if(stggr >= 0) {
    easeH = sel / mod/2
    v = ease(stggr, 0, 100, sel, easeH);
    }
    pos = effect("Position")("Point");
    delay = textIndex*thisComp.frameDuration*2;
    p = pos.valueAtTime(time - delay);
    p*v/1000;

    The expression control Point – Effect named “Position” will determine the position of the animator (along with the funky easing function you wrote), if its value is keyframed, the letters will move with 2 frames delay. (you can also hook that up to a slider of course, or finetune it in another way).

    Important: the value set in the position parameter of the animator needs to be fixed at 1000 (or something else like 100.000, but it needs to be the same as value the v/1000 in the last line of the expression) and it needs to be more than the maximum distance you would want to move the letters around.

    This is what makes it possible to use the expression-selector as sort of an absolute positioner which is what we need here to do the delay.

    If this value itself is keyframed, then it doesn’t work, because amount is limited form -100 to +100%, so say it becomes 50px, but 1 of the letters needs to be positioned still at 60 pixels because it is lagging, we can’t give it 120% to end up at 60.
    Using a very high fixed number for the position-value and then using small amount-percentages gives us all the flexibility.

  • Julian Chojnacki

    January 22, 2023 at 8:09 pm

    Filip, thank you so much! This is spot on, I got exactly what I wanted out of it! 🙂

    One tiny thing I had to modify, though, was how the delay behaves. Initially, the delay started at the very top and progressed down each row, while I needed the top and bottom half to reflect each other.

    This tweak did it:

    const pos = effect("Position")("3D Point");

    const delaySldr = effect("Time Delay")("Slider");

    const delay = textIndex*thisComp.frameDuration*effect("Time Delay")("Slider");

    const p = textIndex < textTotal/2 ? pos.valueAtTime(time + delay) : pos.valueAtTime(time+(delaySldr/3)- delay);

    Assuming 9 rows of text, dividing delaySldr by 3 made the timing pixel perfect for the second half of the text. The only issue is that this currently doesn’t respond to changes in the amount of rows. (See attachment)
    Whenever I change that number, I need to recalculate what delaySldr is divided by. But I can’t for the life of me figure out how to determine that.

    As an example, for 7 rows, I eyeballed that 3.75 works, and for 5 rows it’s 5. Maybe there is an elegant solution to calculate this automatically…

    Do you have any ideas? I really appreciate your knowledge.

  • Filip Vandueren

    January 23, 2023 at 11:58 am

    Try this: I reworked it a bit so we work around the quirk that textIndex is not 0 based, the result is a bit more symmetrical and works for even and odd copies of the text. (although I take it you are only working with odd numbers)

    const flip = effect("Flip")("Checkbox");
    const stggr = effect("Stagger")("Slider");
    const pos = effect("Position")("Point");
    const delay = effect("Time Delay")("Slider").value * thisComp.frameDuration;
    const tot = textTotal-1;
    const ind = textIndex-1;
    const range = tot/2;
    const offst = range - ind;
    const rO = offst/range;
    const mod = Math.cos(Math.PI*2 + rO*2) + 1;
    let sel = linear(ind, 0, tot, -100, 100);
    sel = ind > range && flip == 1 ? -sel : sel;
    if(stggr <= 0) {
    easeL = sel * mod;
    v = ease(stggr, -100, 0, easeL, sel);
    } else if(stggr >= 0) {
    easeH = sel / mod/2;
    v = ease(stggr, 0, 100, sel, easeH);
    }
    const p = ind < range ?
    pos.valueAtTime(time - delay*ind)
    :
    pos.valueAtTime(time- delay*(tot-ind));
    p*v/1000;
  • Julian Chojnacki

    January 23, 2023 at 7:27 pm

    Getting fantastic results, Filip. Thanks a bunch.

    One outstanding thing I noticed with your code is that the delay works either starting inwards, or outwards of the comp’s center depending on whether the delay time is negative or positive.

    I also remember that previously, when the first keyframe of an animation was the absolute position, I had to compensate for the delay by shifting the keyframes forward a bit, which isn’t necessary anymore. I couldn’t be happier!

Page 1 of 2

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