Creative Communities of the World Forums

The peer to peer support community for media production professionals.

Activity Forums Adobe After Effects Expressions converting keyframe velocity to bezier curves

  • converting keyframe velocity to bezier curves

    Posted by Mark Pearce on September 24, 2014 at 2:15 pm

    I’m trying to get a better understanding of the keyframe velocity dialog so that I can convert these keyframe values into Cubic Bezier pairs which could be used in code [for example in CSS cubicBezier(0,0,.3,.7)]

    https://cubic-bezier.com/

    In After Effects each key has two properties. Influence and speed. By combining these two we see the bezier control point that determines the curve.

    Influence is easy enough, it determines the X position of the control point. From 0-100% of the distance between keys. This maps directly to to the 0-1 range.

    Speed is more difficult. The units depend on the property (pixels/second, percent/second, degrees/second)

    The slope of the speed value is the angle of the line drawn between the control point and the key. This angle remains constant no matter what the influence is, and so determines the Y position of the control point.

    My question is how do you calculate the slope angle? With that, you could use trig to get the resulting y position of the control point.

    or if i’m on the totally wrong track…

    How do you convert the speed value to the Y position of the control point?

    feels like i’m getting closer to the answer… just not quite there….

    -Mark

    Adan Ronzon replied 5 years, 10 months ago 4 Members · 4 Replies
  • 4 Replies
  • Hernan Torrisi

    January 1, 2015 at 2:01 pm

    Hi, did you get somewhere with this? Are you still looking?
    I’m on the same track you are.
    I got the answer for one dimensional properties, but I can’t figure out how to extend it to multi dimensional ones.
    I started here but as far as I know, they made some mistakes.
    https://forums.adobe.com/thread/1361143

    This is what I got so far. It’s a script, not an expression but should be the same. It works with properties like rotation, but not with position, or anchor point.
    For multidimensional properties I think the speed should be decomposed into each axis, but I’m not sure how.

    key = {};
    lastKey = {};
    key.time = property.keyTime(2);
    lastKey.time = property.keyTime(1);
    key.value = property.keyValue(2);
    lastKey.value = property.keyValue(1);
    key.easeIn = {
    influence : property.keyInTemporalEase(2)[0].influence,
    speed : property.keyInTemporalEase(2)[0].speed
    }
    lastKey.easeOut = {
    influence : property.keyOutTemporalEase(1)[0].influence,
    speed : property.keyOutTemporalEase(1)[0].speed
    }
    duration = key.time - lastKey.time;
    diff = key.value - lastKey.value;
    averageSpeed = diff/duration;
    bezierIn = {};
    bezierOut = {};
    bezierIn.x = 1 - key.easeIn.influence / 100;
    bezierIn.y = 1 - (key.easeIn.speed / averageSpeed) * (key.easeIn.influence / 100);
    bezierOut.x = lastKey.easeOut.influence / 100;
    bezierOut.y = (lastKey.easeOut.speed / averageSpeed) * bezierOut.x;

  • Manny Gonzalez

    March 4, 2015 at 5:47 am

    I found a script that converts the influence and speed of keyframes into cubic-bezier points here:

    https://forums.adobe.com/thread/1471138

    It’s really helped me out a lot for translating motion curves to web and app developers.

    -Manny

    function getCubicbeziers(){
    var curItem = app.project.activeItem;
    var selectedLayers = curItem.selectedLayers;
    var selectedProperties = app.project.activeItem.selectedProperties;
    if (selectedLayers == 0){
    alert("Please Select at least one Layer");
    }
    else if(selectedLayers !=0){
    for (var i = 0; i < selectedLayers.length; i++){
    for (var f in selectedProperties){
    var currentProperty = selectedProperties[f];
    if (currentProperty.numKeys > 1){
    for(var i = 1; i < currentProperty.numKeys; i++){
    var t1 = currentProperty.keyTime(i);
    var t2 = currentProperty.keyTime(i+1);
    var val1 = currentProperty.keyValue(i);
    var val2 = currentProperty.keyValue(i+1);
    var delta_t = t2-t1;
    var delta = val2-val1;
    avSpeed = Math.abs(val2-val1)/(t2-t1);

    if (val1<val2){//, this should reproduce your website:
    x1 = currentProperty.keyOutTemporalEase(i)[0].influence /100;
    y1 = x1*currentProperty.keyOutTemporalEase(i)[0].speed / avSpeed;

    x2 = 1-currentProperty.keyInTemporalEase(i+1)[0].influence /100;
    y2 = 1-(1-x2)*(currentProperty.keyInTemporalEase(i+1)[0].speed / avSpeed);
    }
    if (val2<val1){//, to get a curve starting from point [0,1] going to point [1,0], it would be:
    x1 = currentProperty.keyOutTemporalEase(i)[0].influence /100;
    y1 = (-x1)*currentProperty.keyOutTemporalEase(i)[0].speed / avSpeed;
    x2 = currentProperty.keyInTemporalEase(i+1)[0].influence /100;
    y2 = 1+x2*(currentProperty.keyInTemporalEase(i+1)[0].speed / avSpeed);
    x2 = 1-x2;
    }
    if (val1==val2){
    x1 = currentProperty.keyOutTemporalEase(i)[0].influence /100;
    y1 = (-x1)*currentProperty.keyOutTemporalEase(i)[0].speed / ((currentProperty.maxValue-currentProperty.minValue)/(t2-t1)) ;
    x2 = currentProperty.keyInTemporalEase(i+1)[0].influence /100;
    y2 = 1+x2*(currentProperty.keyInTemporalEase(i+1)[0].speed / ((currentProperty.maxValue-currentProperty.minValue)/(t2-t1)));
    x2 = 1-x2;
    }
    alert("keyframe: " + i +" Cubic-bezier["+x1+", "+y1 +", "+x2+", "+y2 +"]")

    }
    }
    }
    }
    }

    }
    getCubicbeziers();

  • Hernan Torrisi

    March 4, 2015 at 11:29 pm

    Hi, thanks for sharing. I’ve seen that post and this only works for one dimesional properties.
    If you want to handle multidimensional ones, there are 3 more kinds that need special handling for each case.
    PropertyValueType.SHAPE, where average speed is always 1
    PropertyValueType.ThreeD, PropertyValueType.TwoD and PropertyValueType.TwoD where each dimensions has its own average speed (this is the more similar to the example)
    PropertyValueType.ThreeD_SPATIAL, PropertyValueType.TwoD_SPATIAL, where, to get the average speed, you need to calculate the length of the spatial curve and divide it by the duration.
    In addition to that, for the third case, influence in not well reported in some cases, since AE limits this curve as not to have negative values. So, I made a script to find the real influence.

    I made an AE to html animation exporter during the last 8 months and I’ve just shared it on github, if you want to see the code.
    It’s at https://github.com/bodymovin/bodymovin
    There are some examples of animations exported from after effects.

    If you’re still working on this and want to exchange some ideas, I’d be glad to. It has been a long lonely road to get to this point 🙂

  • Adan Ronzon

    June 16, 2020 at 10:25 pm

    There is a plug in called FLOW that can create your cubic-bezier

    https://aescripts.com/flow/

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