javascripteaseljscreatejseasing

How to achieve ballistic easing effect in TweenJS


Perhaps a simple one, I'm animating along a curved path and wanted to apply an easing profile that eases out on the first half of the tween, and in on the second half. So a fast-slow-fast profile, like a ball has been thrown into the air if that makes sense?

The easing options listed in the TweenJS Spark Table contain some that are pretty much the opposite of what I'm looking for; like cubicInOut for example. Using the previous (poor) description, this would be slow-fast-slow.

I can of course achieve this by chaining tweens using different easing, but this doesn't seem as clean, and there's a pause at the top that would need resolved for this application.

An example showing the cubicInOut at the top, and chained tweens using cubicOut, then cubicIn at the bottom to achieve close to what I'm after.

var stage = new createjs.Stage("canvas");
createjs.Ticker.addEventListener("tick", tick);
createjs.MotionGuidePlugin.install();

var shape1 = new createjs.Shape();
shape1.graphics.f("#000000").dc(0,0,10);

var shape2 = shape1.clone();

var path1 = new createjs.Shape();
path1.graphics.beginStroke("#ff0000").mt(0,100).qt(200,0,400,100);

var path2 = path1.clone();
path2.y = 100;
stage.addChild(path1, path2, shape1, shape2);

createjs.Tween.get(shape1).to({guide:{ path:[0,100, 200,0, 400,100] }},2000, createjs.Ease.cubicInOut);

createjs.Tween.get(shape2).to({guide:{ path:[0,200, 100,150, 200,150] }},1000, createjs.Ease.cubicOut).call(function(){
    createjs.Tween.get(shape2).to({guide:{ path:[200,150, 300,150, 400,200] }},1000, createjs.Ease.cubicIn);
});

function tick(event) {
    stage.update();
}

Fiddle with this example.

Just wondering if there's a cleaner way to achieve this without the need to chain tweens, and without the pause at the apex of the curve? An easing equation seems the simplest, but I'm not sure how I would go about implementing that. Any thoughts would be appreciated.

Many thanks,

Baps.


Solution

  • TweenJS API docs say:

    The Ease class provides a collection of easing functions for use with TweenJS. It does not use the standard 4 param easing signature. Instead it uses a single param which indicates the current linear ratio (0 to 1) of the tween.

    Guided by Custom Easing Functions issue/article on GitHub, there is a way to define your custom function. Just go on and create your Bezier easing function, than transform it to linear.

    You will get this kind of Bezier's function:

    function(t:Number, b:Number, c:Number, d:Number):Number {
        var ts:Number=(t/=d)*t;
        var tc:Number=ts*t;
        return b+c*(0.699999999999999*tc*ts + -1.75*ts*ts + 3.9*tc + -4.1*ts + 2.25*t);
    }
    

    And your TweenJS easing will be:

    var myEasing = function( k ) {
        var t = (k*100);
        var d = 100;
        var ts=(t/=d)*t;
        var tc=ts*t;
        return (0.699999999999999*tc*ts + -1.75*ts*ts + 3.9*tc + -4.1*ts + 2.25*t);
    };
    

    In your code you will use it this way:

    createjs.Tween.get(shape2).to({guide:{ path:[0,200, 200,100, 400,200] }},2000, myEasing);
    

    Check it on updated Fiddle.