Lead Software Developer
It’s very common for animations to be specified as ease-in-out. It’s a very pleasing sensation to witness an object speed up, cruise, and slow to a halt. Most easings specify one of a small number of easing curves: easeInOutQuad, easeInOutSine, easeInOutCubic, etc. However, the sharpness of that curve is not configurable. Here I show how to create a configurable ease-in-out function that will work for animating any property you desire.
The easing function takes a single parameter k, that specifies the steepness of the curve. The larger k is, the steeper the curve, and the higher the velocity in the middle section relative to the beginning and ending.
The sigmoidFactory will produce a function that takes a parameter t that represents the percentage of the animation completed as a number between 0 and 1. It’s important to note that this system only produces numbers that you can use within an animation framework (that you might have to build). An example framework is included in the jsFiddle.
Here is an example of the usage:
var easing = sigmoidFactory(7);
easing(0); // nearly 0 (5.551115123125783e-17)
easing(1); // 1
easing(0.5); // 0.5
easing(0.25); // 0.028453023879735584
easing(0.75); // 0.9715469761202644
This section is not required for use. Read on to understand the techniques underlying the code so that you will be able to develop your own easing curves.
However, these curves both have some defects we’ll have to remedy. We want our animations to start at 0 and end at 1. Both functions begin in the middle of the animation at 0, and asymptotically approach their final values (0 and 1 in the case of sigmoid, -π/2 to π/2 in the case of arctangent).
We’ll need to apply a number of fixes to our chosen function in order to make it ready for service.
I’ve selected the sigmoid curve for our fixes because it’s based on e which is generally easier to analyze than arctangent, though it’s nearly as easy to work with in this case. That exercise will be left to the reader.
Moving the sigmoid is quite easy. Using an algebraic manipulation, if our easing function is f(t), then moving the center point by 0.5 is accomplished by f(t-0.5).
Similarly, if we multiply t by a chosen knob, f(kt), we can make the function “accelerate and condense” if k > 1, or make it “slow and spread out” if k < 1.
In Eqn. 2, we move the manipulations of t into the function in order to make the function easier to use. This solves our first two problems, but take a look at the graph below where Eqn. 2 has been plotted with k = 6.
This is pretty close! However, the beginning and ending of the animation is respectively above 0 and below 1. This will cause an animation to exhibit a “jump” at the ends. If k is set sufficiently high (above about 11 or 12), you won’t even notice the problem. However, this restricts our range of expression as we can’t use any shallow curves, but it might be good enough for you and you can stop here if you so choose.
While your first intuition, as it was mine, might be to find some way to make the sigmoid pass though zero by doing some trick like multiplying by t or using some crazy conditional statements or reflections, there is a simpler way that’s kind of a hack. Notice that the error at the ends of the sigmoid is symmetric — the distance from 0 is the same as the distance from 1. What if we could just scale the result so that 0 passes through 0 and 1 passes through 1?
There are several steps to get this strategy to work, but in brief, you start with a basic sigmoid centered at 0 (so the range is -1/2 to 1/2), multiply by the correction factor (0.5 / f(1)), then figure out how to translate it up (+0.5) and to the right (t-0.5). You then condense the range of the function by 2 (it reaches -0.5 at -1 and +0.5 at 1).
You can find the grapher file here.
Create your free account to unlock your custom reading experience.