Creative Communities of the World Forums

The peer to peer support community for media production professionals.

Activity Forums Adobe After Effects Expressions Adjust keyframes for constant speed along one axis

  • Adjust keyframes for constant speed along one axis

    Posted by James Hamilton on June 27, 2020 at 1:22 pm

    I have an object moving from left to right along a motion path resembling a graph.

    As the object travels from left to right it also travels up and down the spikes, which slows horizontal speed down.

    How can the object be made to travel from left to right at a constant speed, regardless of the ups and downs of the motion path?

    This would require some sort of expression that adjusts the vertical speed in order to maintain a constant horizontal speed. I thought this would be simple to achieve but now I realise it’s deceptively difficult.
    Does anyone know of a technique that could help with this?

    I’d be super grateful for any suggestions at all…I’m tearing my hair out here….

    Here is an image that might help explain: https://ibb.co/FnsRWNH

    James Hamilton replied 5 years, 10 months ago 2 Members · 5 Replies
  • 5 Replies
  • Filip Vandueren

    June 29, 2020 at 11:52 am

    OK,
    a few caveats: this only works for this specific left-to right motion, and given that the motion-path is never tracking back on itself (obviously), so every next keyframe will always have a higher x-value.

    This expression will respect the timing of the first and the last keyframe, and linearize the x-motion (constant speed), then do a crude look-up of what Y-value corresponds to the given X according to the motionpath.

    t1= key(1).time;
    t2= key(numKeys).time;

    x1=key(1).value[0];
    x2=key(numKeys).value[0];

    linear_x=linear(time, t1, t2, x1, x2);

    precision = 3; // make this higher (16) if you need Motion blur
    fd = thisComp.frameDuration/precision;

    y=key(1).value[1];

    for (t=t1; !(t>t2); t+=fd) {
    v=valueAtTime(t);
    if (v[0]>=linear_x) {
    y=v[1];
    break;
    }
    }

    [linear_x,y];t1= key(1).time;
    t2= key(numKeys).time;

    x1=key(1).value[0];
    x2=key(numKeys).value[0];

    linear_x=linear(time, t1, t2, x1, x2);

    precision = 3; // make this higher (16) if you need Motion blur
    fd = thisComp.frameDuration/precision;

    y=key(1).value[1];

    for (t=t1; !(t>t2); t+=fd) {
    v=valueAtTime(t);
    if (v[0]>=linear_x) {
    y=v[1];
    break;
    }
    }

    [linear_x,y];

  • James Hamilton

    June 29, 2020 at 12:25 pm

    Wow, thanks. That is complex!
    I can’t try it right now but will later today…

  • Filip Vandueren

    June 29, 2020 at 12:30 pm

    OK, let me know.

    I just noticed I accidentally pasted the expression-code twice though…

    t1= key(1).time;
    t2= key(numKeys).time;

    x1=key(1).value[0];
    x2=key(numKeys).value[0];

    linear_x=linear(time, t1, t2, x1, x2);

    precision = 3; // make this higher (16) if you need Motion blur
    fd = thisComp.frameDuration/precision;

    y=key(1).value[1];

    for (t=t1; !(t>t2); t+=fd) {
    v=valueAtTime(t);
    if (v[0]>=linear_x) {
    y=v[1];
    break;
    }
    }

    [linear_x,y];

  • James Hamilton

    June 29, 2020 at 12:34 pm

    Thanks for pointing that out.
    It’s shortened length makes it a little less scary at least…

  • James Hamilton

    June 29, 2020 at 5:07 pm

    It works perfectly! This really helps me out, thank you so much.
    Last time I coded was Basic language at school but this has renewed my interest.

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