16
motion

interpolation

interpolation involves finding values between others. it is the core of a keyframe animation system, where key values are set on disparate frames, and the system must interpolate between them to find values for the in-between frames.

to find an interpolated value, you need three things: the starting value, the ending value, and the progress made between the two. for discussion here, we'll call the starting value A, the ending value B, and the progress t, which will be in the range [0,1].

one way to think about interpolating values is to imagine walking a path between A and B. when t is 0, you've made no progress, and are at point A. as t increases, you advance towards B, and by the time t is 1, your progress is complete, and you've arrived at B.

linear interpolation (lerp)

the intuitive path between A and B would be a straight line, and this is what we get with linear interpolation.

we find the distance in a straight line between A and B, scale this by our progress to obtain completed distance, and then add this to A to find our current position:

function lerp(a:Number, b:Number, t:Number):Number {
    var totalDistance:Number = b - a;
    var distanceTraveled:Number = totalDistance * t;
    var currentPosition:Number = a + distanceTraveled;
    return currentPosition;
}

or, more compactly:

function lerp(a:Number, b:Number, t:Number):Number {
    return a + ((b - a) * t);
}

easing

but the straight line from a to b implies a constant, uniform speed. for animation, it's often better to have a variable rate of acceleration or deceleration (a.k.a ease-in and ease-out).

portions of sine

mapping a linearly changing value to portions of the sine curve yields eased values:


ease in
 
function easeIn(linearT) {
      var curveStart = 3*Math.PI/2;
      var curveEnd = 2*Math.PI;
      var curveRange = curveEnd - curveStart;
      var traveledBit = (linearT * curveRange) + curveStart;
      var easyT = 1 + Math.sin(traveledBit);
      return easyT;
}

ease out
 
function easeOut(linearT) {
      var curveStart = 0;
      var curveEnd = Math.PI/2;
      var curveRange = curveEnd - curveStart;
      var traveledBit = (linearT * curveRange) + curveStart;
      var easyT = Math.sin(traveledBit);
      return easyT;
}

smooth
 
function smooth(linearT) {
      var curveStart = 3*Math.PI/2;
      var curveEnd = Math.PI/2;
      var curveRange = curveEnd - curveStart;
      var traveledBit = (linearT * curveRange) + curveStart;
      var doubleT = Math.sin(traveledBit);
      var easyT = (doubleT + 1) * .5;
      return easyT;
}

bias and gain

there are two classic functions, called bias and gain that give us almost all the control we could want over the rate at which t progresses from 0 to 1.

bias

bias takes two parameters, both in the range [0,1]:
  1. the bias amount. values under .5 ease in, values over .5 ease out
  2. the linear progress variable (t)
function bias(b:Number, t:Number):Number {
   return t / ((1/b - 2) * (1-t) + 1);
}
bias = .05 bias = .2 bias = .8 bias = .95

gain

gain also takes two parameters, both in the range [0,1]:
  1. the gain amount. values under .5 ease at the ends, values over .5 ease through the middle
  2. the linear progress variable (t)
function gain(g:Number, t:Number):Number {
   var n:Number = (1/g - 2) * (1 - 2*t);
   if (t < .5) { return t / (n + 1); }
   else  { return (n - t) / (n - 1); }
}
gain = .05 gain = .2 gain = .8 gain = .95

examples

fl.transitions.Tween

while coding your own interpolation handler gives you more control, tweening is such a common aspect of interactive applications that many frameworks provide utilities to make interpolating, or 'tweening' motion easier.

flash provides the Tween class:

import fl.transitions.Tween;
import fl.transitions.easing.Regular;

var L:Number = ball.width * 2;
var R:Number = stage.stageWidth - L;
var sec:Number = 3;
var isSeconds:Boolean = true;

var tween:Tween = new Tween(ball, "x", Regular.easeIn, L, R, sec, isSeconds);
example

 

graphs of common function families

mathematicians have done a lot of work to document numerical properties, relationships, trends, phenomena, rules, behavior, and more. there is so much to take advantage of. if we only gain an awareness of numerical qualities, we can begin to match them to graphical characteristics.

as a general beginning, here are some common families of functions and their basic shapes.

constant
y = n

n
 
power
y = xn

n is even
 

n is odd
 
root
y = x1/n

n is even
 

n is odd
 
exponential
y = nx

n < 1
 

n > 1
 
logarithmic
y = lognx

n < 1
 

n > 1
 
trigonometric
y = sin n
y = cos n

sin n
 

cos n
 

without worrying too much about the math behind the functions, it will help you greatly to at least recognize the general shapes of the classes of functions, because these are the basic sculpting tools of value ranges. the more control you have over the range of values you're processing, the more control you have over the final output.