After finishing the rustwasm Game of Life tutorial I'm trying to implement the whole example in rust using web-sys, including event handlers. I've been able to port the rendering, and straightforward button handling, the only javascript that is left is the animation based on window.requestAnimationFrame
:
import { Universe, Cell, Renderer, ... } from "wasm-game-of-life";
const universe = Universe.new();
const canvas = document.getElementById("game-of-life-canvas");
const renderer = Renderer.new(canvas, universe);
let animationId = null;
const renderLoop = () => {
universe.tick();
renderer.draw();
animationId = requestAnimationFrame(renderLoop);
};
const isPaused = () => {
return animationId === null;
};
const playPauseButton = document.getElementById("play-pause");
const play = () => {
playPauseButton.textContent = "⏸";
renderLoop();
};
const pause = () => {
playPauseButton.textContent = "â–¶";
cancelAnimationFrame(animationId);
animationId = null;
};
playPauseButton.addEventListener("click", event => {
if (isPaused()) {
play();
} else {
pause();
}
});
play();
The problem, for me, is to implement this using Closure
without leaking every frame while recreating it. The closure examples in the guide are all about event handlers that are called repeatedly. However, in this case it is necessary to re-set the event handler after every frame.
Ideally the closure itself needs to be able to pass itself again into requestAnimationFrame
. But it eludes me how to do this, say, what to put in the …
here:
// renderLoop
{
let closure: Closure<FnMut()> = Closure::wrap(Box::new(move || {
log("animation frame");
let window = web_sys::window().expect("no global `window` exists");
window.request_animation_frame(…);
}));
let window = web_sys::window().expect("no global `window` exists");
window.request_animation_frame(closure.as_ref().unchecked_ref());
closure.forget();
}
(I've tried to think of various ways to wrap using Cell
, Rc
, Box
, or wrapping the Closure into my own struct, but nothing worked… I suspect I'm thinking in the wrong direction completely !)