Source file reposition_hook.ml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
open! Core
open Virtual_dom
open Js_of_ocaml
include Vdom.Attr.Hooks.Make (struct
module State = struct
type t =
{ mutable current_transform : int
; mutable anim_frame_id : Dom_html.animation_frame_request_id option
}
end
module Input = struct
type t = unit [@@deriving sexp_of]
let combine _ _ = ()
end
let safe_screen_margin = 12
let step (state : State.t) element =
let frame_width, frame_offset = Dom_html.window##.innerWidth, 0 in
let element_width = element##.clientWidth in
let offset =
let total_offset = element##getBoundingClientRect##.left |> Float.to_int in
total_offset - state.current_transform - frame_offset
in
let total_width = offset + element_width + safe_screen_margin in
let delta =
if frame_width < total_width
then frame_width - total_width
else if offset - safe_screen_margin < 0
then -(offset - safe_screen_margin)
else 0
in
if state.current_transform <> delta
then (
state.current_transform <- delta;
element##.style##.transform := Js.string [%string "translate(%{delta#Int}px, 0px)"])
;;
let reposition_until_stopped state ~element =
let rec loop () =
step state element;
let next_frame_anim_id =
Dom_html.window##requestAnimationFrame (Js.wrap_callback (fun _ -> loop ()))
in
state.anim_frame_id <- Some next_frame_anim_id
in
element##.style##.opacity := Js.Optdef.return (Js.string "");
loop ()
;;
let init () element =
element##.style##.opacity := Js.Optdef.return (Js.string "0");
{ State.anim_frame_id = None; current_transform = 0 }
;;
let on_mount () state element = reposition_until_stopped state ~element
let on_mount = `Schedule_animation_frame on_mount
let update ~old_input:() ~new_input:() _state _element = ()
let destroy () (state : State.t) element =
Option.iter state.anim_frame_id ~f:(fun anim_frame_id ->
Dom_html.window##cancelAnimationFrame anim_frame_id);
element##.style##.transform := Js.string ""
;;
end)