use std::cell::Cell; use std::rc::Rc; use wasm_bindgen::closure::Closure; use wasm_bindgen::JsCast; pub struct AnimationFrameHandler { window: web_sys::Window, closure: Closure, handle: Rc>>, } impl AnimationFrameHandler { pub fn new(window: web_sys::Window) -> Self { let handle = Rc::new(Cell::new(None)); let closure = Closure::new({ let handle = handle.clone(); move || handle.set(None) }); Self { window, closure, handle, } } pub fn on_animation_frame(&mut self, mut f: F) where F: 'static + FnMut(), { let handle = self.handle.clone(); self.closure = Closure::new(move || { handle.set(None); f(); }) } pub fn request(&self) { if let Some(handle) = self.handle.take() { self.window .cancel_animation_frame(handle) .expect("Failed to cancel animation frame"); } let handle = self .window .request_animation_frame(self.closure.as_ref().unchecked_ref()) .expect("Failed to request animation frame"); self.handle.set(Some(handle)); } pub fn cancel(&mut self) { if let Some(handle) = self.handle.take() { self.window .cancel_animation_frame(handle) .expect("Failed to cancel animation frame"); } } } impl Drop for AnimationFrameHandler { fn drop(&mut self) { if let Some(handle) = self.handle.take() { self.window .cancel_animation_frame(handle) .expect("Failed to cancel animation frame"); } } }