1use wasm_bindgen::prelude::*;
2use wasm_bindgen::JsCast;
3use std::rc::Rc;
4use std::cell::RefCell;
5
6pub struct Raf {
7 state: Rc<RefCell<Option<RafState>>>,
8}
9
10struct RafState {
11 id: i32,
12 closure: Closure<dyn FnMut(f64)>,
13}
14
15impl Raf {
16 pub fn new<F>(mut callback: F) -> Self where F: FnMut(f64) + 'static {
17 let state: Rc<RefCell<Option<RafState>>> = Rc::new(RefCell::new(None));
18
19 fn schedule(callback: &Closure<dyn FnMut(f64)>) -> i32 {
20 web_sys::window()
21 .unwrap_throw()
22 .request_animation_frame(callback.as_ref().unchecked_ref())
23 .unwrap_throw()
24 }
25
26 let closure = {
27 let state = state.clone();
28
29 Closure::wrap(Box::new(move |time| {
30 {
31 let mut state = state.borrow_mut();
32 let state = state.as_mut().unwrap_throw();
33 state.id = schedule(&state.closure);
34 }
35
36 callback(time);
37 }) as Box<dyn FnMut(f64)>)
38 };
39
40 *state.borrow_mut() = Some(RafState {
41 id: schedule(&closure),
42 closure
43 });
44
45 Self { state }
46 }
47}
48
49impl Drop for Raf {
50 fn drop(&mut self) {
51 let state = self.state.borrow_mut().take().unwrap_throw();
53
54 web_sys::window()
55 .unwrap_throw()
56 .cancel_animation_frame(state.id)
57 .unwrap_throw();
58 }
59}