ui icon indicating copy to clipboard operation
ui copied to clipboard

Animation can go past its end value

Open Bananas-Are-Yellow opened this issue 8 years ago • 2 comments

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:

  1. A new animation frame is only requested if t <= dur, but if anim.Compute t takes some time, t can be out of date. In my case I am using Anim.Map to cause a side effect, which is to rotate a WebGL view. Maybe there is a better way to do this.
  2. Regardless of (1), when the time comes to compute the next frame, t can be greater than dur, and anim.Compute converts this to a value past the endValue.

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.

Bananas-Are-Yellow avatar May 06 '16 07:05 Bananas-Are-Yellow

Actually, hold off from investigating this for now. My understanding of what's going on is not quite accurate ...

Bananas-Are-Yellow avatar May 06 '16 07:05 Bananas-Are-Yellow

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

Bananas-Are-Yellow avatar May 06 '16 08:05 Bananas-Are-Yellow