首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >当将Rust编译为wasm (web程序集)时,我如何睡眠10毫秒?

当将Rust编译为wasm (web程序集)时,我如何睡眠10毫秒?
EN

Stack Overflow用户
提问于 2019-09-03 06:18:47
回答 2查看 2.7K关注 0票数 8

我的生锈程序正在为2d html画布上下文管理内存,我正在尝试命中~60 for。我可以很容易地计算出每一帧之间的增量,结果大约是5毫秒。

我不清楚如何将我的锈菌组件程序用于其余11毫秒的睡眠。一种选择是让JavaScript在每个requestAnimationFrame上调用Rust,并使用它作为驱动程序,但我很好奇,如果可能的话,我想把它保存在Rust中。

在编译到wasm目标时,我实际上是在寻找与JavaScript的setTimeout(renderNext, 11)等效的Rust。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-09-03 07:25:34

在编译到wasm目标时,我实际上是在寻找与JavaScript的setTimeout(renderNext, 11)等效的Rust。

有几个锈蚀板条箱绑定到JavaScript web,最显著的是web-sys。看看 overloads

不过,这实际上并不等同于锈蚀,因为它非常直接地调用JS函数。但是,您将无法绕过这个问题:睡眠或获取当前时间都是主机环境必须提供的功能。它们不能仅用原始语言实现。

一种选择是让JavaScript在每个requestAnimationFrame上调用Rust,并使用它作为驱动程序,但我很好奇,如果可能的话,我想把它保存在Rust中。

是的,您应该使用requestAnimationFrame ( docs)。这比自己选择时间要好得多。特别是,当选项卡不活动时,此方法也会暂停调用代码,诸如此类。在桌面环境中,您也会这样做:要求主机环境(即操作系统,通常通过OpenGL左右)同步您的程序以进行屏幕刷新。

票数 2
EN

Stack Overflow用户

发布于 2020-08-30 05:05:38

在您的requestAnimationFrame回调中,调用setTimeout,然后再调用requestAnimationFrame。您可以看到这个here的JS版本。

基于 book,下面是我如何在Rust中这样做的:

代码语言:javascript
复制
fn animate_limited(mut draw_frame: impl FnMut() + 'static, max_fps: i32) {
    // Based on:
    // https://rustwasm.github.io/docs/wasm-bindgen/examples/request-animation-frame.html#srclibrs

    // https://doc.rust-lang.org/book/ch15-05-interior-mutability.html
    let animate_cb = Rc::new(RefCell::new(None));
    let animate_cb2 = animate_cb.clone();

    let timeout_cb = Rc::new(RefCell::new(None));
    let timeout_cb2 = timeout_cb.clone();

    let w = window();
    *timeout_cb2.borrow_mut() = Some(Closure::wrap(Box::new(move || {
        request_animation_frame(&w, animate_cb.borrow().as_ref().unwrap());
    }) as Box<dyn FnMut()>));

    let w2 = window();
    *animate_cb2.borrow_mut() = Some(Closure::wrap(Box::new(move || {
        draw_frame();

        set_timeout(&w2, timeout_cb.borrow().as_ref().unwrap(), 1000 / max_fps);
    }) as Box<dyn FnMut()>));

    request_animation_frame(&window(), animate_cb2.borrow().as_ref().unwrap());
}

fn window() -> web_sys::Window {
    web_sys::window().expect("no global `window` exists")
}

fn request_animation_frame(window: &web_sys::Window, f: &Closure<dyn FnMut()>) -> i32 {
    window
        .request_animation_frame(f.as_ref().unchecked_ref())
        .expect("should register `requestAnimationFrame` OK")
}

fn set_timeout(window: &web_sys::Window, f: &Closure<dyn FnMut()>, timeout_ms: i32) -> i32 {
    window
        .set_timeout_with_callback_and_timeout_and_arguments_0(
            f.as_ref().unchecked_ref(),
            timeout_ms,
        )
        .expect("should register `setTimeout` OK")
}

然后,您只需向animate_limited传递一个函数来完成绘图(像move || { /* drawing logic here */ }这样的闭包就可以了),以及您想要的最大框架。

几乎可以肯定地说,在这方面还需要改进。我对锈病非常陌生,只是花了很长时间才弄明白如何使这件事奏效。希望这能让其他人在未来更快。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/57765987

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档