Implement requestAnimationFrame for web (#1519)

* Use requestAnimationFrame for polling wasm

* Implement `requestAnimationFrame` for stdweb

Co-authored-by: Ryan G <ryanisaacg@users.noreply.github.com>
This commit is contained in:
Jurgis 2020-04-11 22:49:07 +03:00 committed by GitHub
parent a8e777a5df
commit 1f24a09570
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 93 additions and 6 deletions

View file

@ -1,3 +1,5 @@
use std::cell::Cell;
use std::rc::Rc;
use std::time::Duration;
use wasm_bindgen::closure::Closure;
use wasm_bindgen::JsCast;
@ -38,3 +40,48 @@ impl Drop for Timeout {
window.clear_timeout_with_handle(self.handle);
}
}
#[derive(Debug)]
pub struct AnimationFrameRequest {
handle: i32,
// track callback state, because `cancelAnimationFrame` is slow
fired: Rc<Cell<bool>>,
_closure: Closure<dyn FnMut()>,
}
impl AnimationFrameRequest {
pub fn new<F>(mut f: F) -> AnimationFrameRequest
where
F: 'static + FnMut(),
{
let window = web_sys::window().expect("Failed to obtain window");
let fired = Rc::new(Cell::new(false));
let c_fired = fired.clone();
let closure = Closure::wrap(Box::new(move || {
(*c_fired).set(true);
f();
}) as Box<dyn FnMut()>);
let handle = window
.request_animation_frame(&closure.as_ref().unchecked_ref())
.expect("Failed to request animation frame");
AnimationFrameRequest {
handle,
fired,
_closure: closure,
}
}
}
impl Drop for AnimationFrameRequest {
fn drop(&mut self) {
if !(*self.fired).get() {
let window = web_sys::window().expect("Failed to obtain window");
window
.cancel_animation_frame(self.handle)
.expect("Failed to cancel animation frame");
}
}
}