ui
ui copied to clipboard
Animation can go past its end value
An animation has a duration
, a startValue
and an endValue
.
Here is Anim.Run:
static member Run k anim =
let dur = anim.Duration
Async.FromContinuations <| fun (ok, _, _) ->
let rec loop start now =
let t = now - start
k (anim.Compute t)
if t <= dur then
JS.RequestAnimationFrame (fun t -> loop start t) |> ignore
else ok ()
JS.RequestAnimationFrame (fun t -> loop t t) |> ignore
There are two problems:
- A new animation frame is only requested if
t <= dur
, but ifanim.Compute t
takes some time,t
can be out of date. In my case I am usingAnim.Map
to cause a side effect, which is to rotate a WebGL view. Maybe there is a better way to do this. - Regardless of (1), when the time comes to compute the next frame,
t
can be greater thandur
, andanim.Compute
converts this to a value past theendValue
.
My workaround is to use a custom interpolation, which clamps the resulting value:
type ClampedInterpolation =
| ClampedInterpolation
interface Interpolation<double> with
member __.Interpolate t x y =
if t <= 0. then x
elif t >= 1. then y
else x + t * (y - x)
This also provides protection in case a custom Easing maps t
to be outside the range.
Actually, hold off from investigating this for now. My understanding of what's going on is not quite accurate ...
OK, so the problem is not quite what I described. The problem is 'bounce back' caused by a value of t
exceeding 1.0 (for the reasons I said), and then the Easing.CubicInOut
function converting this into a value slightly less than 1.0. So the workaround is to clamp the easing function, not the interpolation.
let easing t =
if t <= 0. then 0.
elif t >= 1. then 1.
else else Easing.CubicInOut.TransformTime t
Easing.Custom easing