16interpolation 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.
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); }
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).
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; } |
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 takes two parameters, both in the range [0,1]:
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 also takes two parameters, both in the range [0,1]:
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 |
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
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.
graphs]
gTween]
HydroTween]
Tween]
Tweener]
TweenLite]
comparison)