是否可以从Web程序集中有效地修改html5画布?
更新:
var imageData = context.getImageData(x, y, w, h)
var buffer = imageData.data.buffer; // ArrayBuffer
如果缓冲区可写,可能就是这样。
答案 0 :(得分:4)
WebAssembly实例通常具有线性内存区域,该区域作为arraybuffer向JavaScript API公开。这可以在JS中分配,并在创建WebAssembly实例时传入,或者WebAssembly实例可以创建它并将其导出到JS代码。无论哪种方式,arraybuffer都可以用来有效地将数据复制到Canvas元素中和从Canvas元素中复制出来(使用createImageData,getImageData和putImageData)。
答案 1 :(得分:4)
不,不是在WebAssembly和web-api开发的这个阶段。
使用context.getImageData
,您将获得一个带有新缓冲区的新ImageData
对象,该缓冲区必须再次复制到WebAssembly实例的内存缓冲区中。
但是,如果您不需要从画布中读取,只需要编写,则可以在WebAssembly实例的内存中分配ImageData.data
。使用ImageData构造函数
imageData = new ImageData(new Uint8ClampedArray(waInstance.export.memory.buffer, byteOffset, width*height*4), width, height)
imageData
有一个指向您数据的指针。在每次渲染时,在WebAssembly中完成工作并在imageData
中使用相同的context.putImageData(imageData)
,每个周期只执行一次大数据复制。
答案 2 :(得分:3)
WebAssembly.Memory
个实例。然后修改并复制回来。Uint8Array.set()
在最新的Chrome中并不快。最好将数据重新转换为32位(new Uint32Array(your_uint8array)
),然后使用Uint32Array.set()
进行复制。.getImageData()
/ .setImageData()
并不快。也许,因为他们做alpha预乘和其他事情。总结一下:你的最大速度损失将在.getImageData / .setImageData中,并且无法避免。其他事情有解决方法。
如果与优化的JS相比,ism会给你10-20%的好处,而不是太多。
答案 3 :(得分:0)
我知道一种解决方案已被接受,但是如果有人落在这里寻找替代方案,我还是会张贴。
我没有积极参与wasm-bindgen防锈工具的开发,但是它目前能够通过网络系统的箱子修改canvas元素。下面显示的代码摘自wasm-bindgen图书页面上的链接。
use std::f64;
use wasm_bindgen::prelude::*;
use wasm_bindgen::JsCast;
#[wasm_bindgen(start)]
pub fn start() {
let document = web_sys::window().unwrap().document().unwrap();
let canvas = document.get_element_by_id("canvas").unwrap();
let canvas: web_sys::HtmlCanvasElement = canvas
.dyn_into::<web_sys::HtmlCanvasElement>()
.map_err(|_| ())
.unwrap();
let context = canvas
.get_context("2d")
.unwrap()
.unwrap()
.dyn_into::<web_sys::CanvasRenderingContext2d>()
.unwrap();
context.begin_path();
// Draw the outer circle.
context
.arc(75.0, 75.0, 50.0, 0.0, f64::consts::PI * 2.0)
.unwrap();
// Draw the mouth.
context.move_to(110.0, 75.0);
context.arc(75.0, 75.0, 35.0, 0.0, f64::consts::PI).unwrap();
// Draw the left eye.
context.move_to(65.0, 65.0);
context
.arc(60.0, 65.0, 5.0, 0.0, f64::consts::PI * 2.0)
.unwrap();
// Draw the right eye.
context.move_to(95.0, 65.0);
context
.arc(90.0, 65.0, 5.0, 0.0, f64::consts::PI * 2.0)
.unwrap();
context.stroke();
}
可以从转换为Web程序集的rust代码访问canvas对象。调用Web汇编代码的方式有很多,但是此示例建议的方法是一个包含这些内容的index.js文件,以及一个诸如webpack的捆绑器。
import("path/to/wasm/canvas/code").catch(console.error)
有关此内容的端到端演示,请访问此链接作为参考。