Creative Communities of the World Forums

The peer to peer support community for media production professionals.

Activity Forums Adobe After Effects Expressions Value in relation to keyframes

  • Value in relation to keyframes

    Posted by Aaron Pozzer on September 3, 2011 at 3:15 am

    so im not sure how to describe what i want to be able to do here, but ill take a shot.

    i have a particle system being controlled by 2 nulls. 1 null is parented to another object, gets path info etc, and it gives the particle system the xy position. then i parented a seperate null to the 1st, just do deal with z position. so the emitter gets its z position from that 2nd null.

    this is more an issue of me being lazy i guess, but isnt that what expressions are for? if i make time adjustments to the keys that control the xy position, if i dont make sure i also adjust the keys on the z position null, the motion of the path gets messed up. im wondering if there is an expression that will say something like…

    ‘if you are at a keyframe, be 0, if you are not, be 100 (or whatever value), and anywhere in between a key be at the correct percentage of 100 corresponding to how far between keys you are’.

    does that make sense? so if i have a key at frame 1, and a key at frame 10, and i set the CTI to frame 5, the z would calculate a value of 50 because its in the middle. if i set the CTI to frame 3 or 7 it would be 30%, etc… the xy values dont matter, just where their keyframes are.

    basically im trying to make a line that hops around a map, representing a flight, hence why i need z now, as the travelling line is no longer constrained to just driving around ON the map. so this would make the line automatically arc into the air between keys, as the keys usualy mark destinations where the path turns.

    my problem with this is telling it how to figure out where a keyframe is and where it is in relation to other keys. im sure its probably pretty easy.

    looking forward to more expression magic! thanks!

    Zoltán Riskó replied 8 years, 1 month ago 3 Members · 16 Replies
  • 16 Replies
  • Dan Ebberts

    September 3, 2011 at 4:25 am

    I have no idea if this is what you’re looking for, but this expression will generate values between 0 and 100 as the time moves between keyframes of another property (position in this example). Before the first keyframe and after the last keyframe it just sets the result to value.


    p = transform.position; // property you want to monitor
    v = value;
    if (p.numKeys > 0){
    n = p.nearestKey(time).index;
    if (p.key(n).time > time) n--;
    if (n > 0 && n < p.numKeys)
    v = linear(time,p.key(n).time,p.key(n+1).time,0,100);
    }
    v

    Dan

  • Aaron Pozzer

    September 3, 2011 at 12:55 pm

    hey Dan. thanks for the response. so this KINDA works, but not quite.

    i have my null object. lets say it has 4 position keys to its animation, and it just outlines a simple path. lets say the 1st key of this animation is on frame 10.

    when i start at frame 0, the expression calculates the value i entered: -50 (i want the line to come closer to the camera, hence the negative value). as i scrub forward towards frame 10 (the first key), nothing happens. when i hit frame 10 the value is set to 0. as i keep scrubbing towards the next keyframe the value climbs all the way up to -50 and when it hits the next key it resets back down to 0. over and over for as many keys as there are in the animation.

    so, this isnt the desired effect. this creates steps kinda, with the -50 z value always being right before the next key is reached. what i was after was that -50z was always in the middle of any 2 keys. so when its ON a key, its 0, and when its between any 2 keys its trying to get to -50 (or whatever value). the goal is to create arcs with the highest point of the arc being between any 2 keys.

    i suppose using linear would give a series of pyramids/steps rather than arcs. perhaps ease is better suited for this expression?

    anyway, does that make more sense? is it possible?

  • Dan Ebberts

    September 3, 2011 at 3:37 pm

    Something more like this then, probably:


    p = transform.position;
    offset = 0;
    if (p.numKeys > 0){
    n = p.nearestKey(time).index;
    if (p.key(n).time > time) n--;
    if (n > 0 && n < p.numKeys){
    t0 = p.key(n).time;
    t1 = p.key(n+1).time;
    d = t1 - t0;
    t = Math.abs(time - (t0+t1)/2)
    offset = ease(t,0,d/2,-50,0);
    }
    }
    value + offset

    Dan

  • Aaron Pozzer

    September 4, 2011 at 2:53 pm

    thats the ticket! worked great. if i wanted to be SUPER picky id ask if there was a way to increase the offset for the further away keys are. like if keys are more than 10 frames apart offset by ____, if more than 20 frames apart offset by _____… or some automatic scaling factor that would just do it automatically.

    but ya, its fine now as it stands unless you wanna try and solve that one too.

    thanks dan!

  • Dan Ebberts

    September 4, 2011 at 4:30 pm

    This should do it. Adjust variables nom and peak to get the relationship you want.


    p = transform.position;
    offset = 0;
    if (p.numKeys > 0){
    peak = -50;
    nom = 10; // frames
    n = p.nearestKey(time).index;
    if (p.key(n).time > time) n--;
    if (n > 0 && n < p.numKeys){
    t0 = p.key(n).time;
    t1 = p.key(n+1).time;
    d = t1 - t0;
    t = Math.abs(time - (t0+t1)/2)
    offset = ease(t,0,d/2,peak*d/timeToFrames(nom),0);
    }
    }
    value + offset

    Dan

  • Aaron Pozzer

    September 5, 2011 at 2:09 pm

    awesome dan!

    a question about ease. my ideal curve for the line all this stuff is controlling would be this sort of shape…

    https://www.unifycommunity.com/wiki/images/e/e8/Mathfx-Bounce.png

    …where the in and out points are hard, and the arc in the middle is smooth. is there a command like ease that will give this shape instead of the smooth shape of ease?

  • Dan Ebberts

    September 5, 2011 at 11:38 pm

    Maybe you just need to use easeOut() and easeIn() instead of ease(), like this:


    p = transform.position;
    offset = 0;
    if (p.numKeys > 0){
    peak = -50;
    nom = 10; // frames
    n = p.nearestKey(time).index;
    if (p.key(n).time > time) n--;
    if (n > 0 && n < p.numKeys){
    t0 = p.key(n).time;
    t1 = p.key(n+1).time;
    d = t1 - t0;
    t = (t0+t1)/2;
    if (time <= t)
    offset = easeOut(time,t0,t,0,peak*d/framesToTime(nom))
    else
    offset = easeIn(time,t,t1,peak*d/framesToTime(nom),0);
    }
    }
    value + offset

    I also corrected an error in the previous version where I was using timeToFrames() instead of framesToTime().

    If this doesn’t give you what you want, you may need to implement your own quadratic or cubic easing function.

    Dan

  • Aaron Pozzer

    September 7, 2011 at 12:55 pm

    hey Dan. thanks for making the above adjustment. i didnt even notice till just now when i came here to ask another follow up question. so, im trying to be proactive and figure stuff out for myself, but not having much luck.

    im trying to modify the 1st expression you posted (since its the simplest) to serve as a general purpose monitor for the same property im trying to watch and drive the Z position of that null.

    i want it to be able to drive things like opacity, birth rate, etc, on any property i want, so things will all turn on/off in relation to those keys, and i only have to animate one channel basically.

    but!… the modification i was trying to make would seem to only require the time of the 1st and last keys. if i wanted to fade something in at the 1st key, and then fade it out at the last, any keys in between wouldnt matter.

    i had a look at the options available. im not sure key(index) would work, cause the # of keys might change… so only the 1st key would be the same. nearestkey would use them all i think, so thats no good, and key(markerName)… well im not sure on this one. i dont know how to set a marker name for a key, unless it means just a regular marker with you set with the * key?

    then i guess the other problem would be, once it hits the 1st key and the opacity is triggered to raise from 0 to 100, does that happen instantly? i guess so, unless you tell it otherwise… so i wouldnt know how to build in a frame buffer as it were, so it comes on over 5 or 10 frames.

    so if you were to modify the above, im not sure if needs all the fancy easing and such. these just need to turn stuff on.

    thanks again Dan!

  • Dan Ebberts

    September 7, 2011 at 3:18 pm

    This should fade from 0 to 100 at the first position keyframe and 100 to 0 coming into the last keyframe. It won’t do anything unless there are at least two keyframes:


    p = transform.position;
    fadeFrames = 10;

    if (p.numKeys > 1){
    t0 = p.key(1).time;
    t1 = p.key(p.numKeys).time;
    t = framesToTime(fadeFrames);
    if (time < (t0+t1)/2){
    ease(time,t0,t0+t,0,100)
    }else{
    ease(time,t1-t,t1,100,0)
    }
    }else{
    value
    }

    Dan

  • Aaron Pozzer

    September 7, 2011 at 4:06 pm

    great Dan! perfect as always. much appreciated.

Page 1 of 2

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