I'm experimenting in Javascript with animating various elements using a cubic-bezier timing function.
(I know this is usually better done with CSS3, or a Javascript animation library. I'm simply using Javascript here to understand how bezier functions work, and teach myself about them.)
So, I get the basic concept, and I'm using a simple bezier curve library written by Stephen McKamey, which is a great Javascript port of the Webkit implementation.
I'm having trouble understanding how I can actually use this function to control an animation in Javascript. So, starting with something very simple: a basic black square that I can animate by moving it to the right, by incrementing its style.left
property:
CSS:
.parent {
position: relative;
}
.foo {
border: 1px solid #000000;
background-color: black;
height: 200px;
width: 200px;
position: absolute;
}
HTML:
<div class = "parent">
<div class = "foo" id = "target"></div>
</div>
Okay, so, given a cubic bezier function "bezier
", defined as follows:
function bezier(p1x, p1y, p2x, p2y, x, duration) { ... }
Where p1x, p1y, p2x and p2y are the curve control points (between 0 and 1.0), x
is the value of the x
coordinate, and duration
is a duration in milliseconds. The function returns the corresponding y
coordinate. I'm trying to simply animate this black box by moving it 400px
to the right.
For my first attempt, I use the standard "ease" bezier values, which CSS3 uses, so our ease
bezier function could be written as:
function ease(x, duration) {
return function() {
Bezier.cubicBezier(0.25, 0.1, 0.25, 1.0, x, duration);
}
}
So this should give us a slow start, then move fast, then end slowly.
Okay, so I assume the basic way to implement this is to use window.setInterval
, and then for each interval, call the bezier function with a new value for x, and then apply the result somehow to the property we want to animate.
The thing is, I'm not sure what my "x" value is here. I assume that in this situation, x is actually the time, and y is the delta between the old position and new position (distance to move), but I'm not really sure. I'm probably wrong.
Anyway, plugging this all in, I'd write a function like:
var startPos = 0;
var endPos = 400; // pixels
var duration = 400; // milliseconds
var millisecondsPerInterval = 10;
var target = document.getElementById("target");
var t = 0;
var pos = 0;
var bezierFunction = Bezier.cubicBezier;
var interval = window.setInterval(
function() {
pos = pos + bezierFunction(0.25, 0.1, 0.25, 1.0, t / 1000, duration); // "ease" values
target.style.left = (pos * millisecondsPerInterval) + "px";
t += millisecondsPerInterval;
if (t === duration) { window.clearInterval(interval); }
},
millisecondsPerInterval
);
This seems to work - the box slowly begins moving and then speeds up. But then it just stops abruptly, rather than easing out. So I'm probably not applying this function correctly. I'm not even certain if "x
" is supposed to be my time value here, and "y
" is supposed to be the position delta (distance to move), but that seems the only way to apply this that makes any sense.
So, am I doing something wrong here? What is the correct way to apply a cubic bezier function to a property we want to animate using Javascript?