web-apis-websharper/UI/Animate.fs
2025-07-28 01:05:33 -07:00

47 lines
1.8 KiB
Forth

namespace web_api_cookbook.UI
open web_api_cookbook
open web_api_cookbook.Units.Animation
open web_api_cookbook.Units.Time
open WebSharper
open WebSharper.UI
open WebSharper.JavaScript
[<JavaScript>]
module Animate =
let value (startPoint:float) endPoint (targetFps:float<frames/s>) (animationSeconds:float<s>) =
let frameInterval = 1. / targetFps * 1000.0<ms/s>
let frameCount = animationSeconds * targetFps
let diff = startPoint - endPoint
let increment = abs (diff / frameCount)
let lerp = Math.lerp startPoint endPoint
let interpolatedValue = Var.Create startPoint
let rec callback (lastRedrawAt:float<ms> option) frameNo (now:float) =
let now = now * 1.0<ms>
let lastRedrawAt = Option.getOrElse now lastRedrawAt
let elapsed = now - lastRedrawAt
let readyToRender = elapsed >= frameInterval * 1.<frames>
match readyToRender with
| false ->
JS.Window.RequestAnimationFrame (callback (Some lastRedrawAt) frameNo) |> ignore
| true ->
let t = float frameNo * increment * 1.<frames>
let nextVal = lerp t
Var.Set interpolatedValue nextVal
if nextVal <> endPoint
then
JS.Window.RequestAnimationFrame (callback (Some now) (frameNo + 1))
|> ignore
JS.Window.RequestAnimationFrame (callback None 0) |> ignore
interpolatedValue.View
let valueWhen beginAnimation startPoint endPoint targetFps animationSeconds =
function
| true -> value startPoint endPoint targetFps animationSeconds
| false -> View.Const startPoint
|> View.MapCached <| beginAnimation
|> View.Join