So one of the last remaining problems with my animation framework was solved tonight 
Long story short, bezier curves are harder than you'd think, and resuming them are even harder:
Let's say you'd want to animate from 1 to 5 over 5 seconds, but start the value at 2.5…

Long story short, bezier curves are harder than you'd think, and resuming them are even harder:
Let's say you'd want to animate from 1 to 5 over 5 seconds, but start the value at 2.5…
Well it's just interpolation right?
2.5 / 5 is 50%, so 50% of 5s is 2.5s, right?
This is true iff you're using a linear curve.
What about ease-in? ease-out? some random custom bezier curve?
2.5 / 5 is 50%, so 50% of 5s is 2.5s, right?
This is true iff you're using a linear curve.
What about ease-in? ease-out? some random custom bezier curve?
This is where the math gets tricky, and the solution, is actually just clever shortcuts (and if they fail, you brute force your way to the solution with a binary tree search).
When you create a bezier curve you normally hand it two points (p1 and p2, which each have an x and y)
When you create a bezier curve you normally hand it two points (p1 and p2, which each have an x and y)
Now with animation, typically you're using a cubic bezier, so you have 4 points.
You end up getting parametric equations of the form:
y(t) = some stuff
x(t) = some stuff
And you use this to draw the bezier curve (where t is the percent through the curve)
You end up getting parametric equations of the form:
y(t) = some stuff
x(t) = some stuff
And you use this to draw the bezier curve (where t is the percent through the curve)
plot each x,y evaluated, and bam, you have a bezier curve.
Now when you're animating with the curve as an easing function, it's not quite that simple, there's no real function for y(x) (or x(y), which is what we want here)
Now when you're animating with the curve as an easing function, it's not quite that simple, there's no real function for y(x) (or x(y), which is what we want here)
We have a percent animated (which is 2.5/ 5, 50%), in this case, this is the y value, since for an easing curve, y is the percent of the interpolation between two values.
So we have y, and we need x (which is time, remember t is *not* time, it's percent through the curve)
So we have y, and we need x (which is time, remember t is *not* time, it's percent through the curve)
To get x, we need a value t that gives us the time.
How do we get t? Well we can use y and since t has the range of 0 to 1, we just binary search values of t on y(t) until we get the value == y (which we already have)
How do we get t? Well we can use y and since t has the range of 0 to 1, we just binary search values of t on y(t) until we get the value == y (which we already have)
Once we have t, we can just evaluate x(t) to get the time we'll resume from… and we're done!
If you're curious about how this works, here's a more in-depth article about it (vs. tweets)
http://mrcslws.com/blocks/2015/02/26/using-bezier-curves-as-easing-functions.html
Conversely this is how WebKit (and CoreAnimation) work.
As much as people (myself included) dunk on UIKit, `.beginFromCurrentState` is harder than you think!
http://mrcslws.com/blocks/2015/02/26/using-bezier-curves-as-easing-functions.html
Conversely this is how WebKit (and CoreAnimation) work.
As much as people (myself included) dunk on UIKit, `.beginFromCurrentState` is harder than you think!
@mrcslws u da real mvp