如何从 Reason 更新 JS 类型数组?
How do I update a JS Typed Array from Reason?
我正在尝试更新 Canvas 的图像上下文的 ImageData,当我尝试在数据数组中设置元素时,我收到一条错误消息,提示该数组的类型为 Js.Typed_array.Uint8ClampedArray.t
当有预期 array('a)
.
为什么我不能更新 JS TypedArray 实现?
这是我的组件代码(为清楚起见做了一些简化):
let make = _children => {
let map = FeatureMap.make(100, 100);
let (width, height) = map.dimensions;
{...component,
initialState: () => {
map: map,
canvasRef: ref(None)
},
didMount: self => switch (self.state.canvasRef^) {
| None => ()
| Some(canvas) => {
let ctx = getContext2d(canvas);
let imageData = createImageDataCoords(ctx, ~width=float_of_int(width), ~height=float_of_int(height));
let data = Webapi.Dom.Image.data(imageData);
Array.iteri((x, row) => {
Array.iteri((y, weight) => {
let index = (x * width + y) * 4;
let (r, g, b) = weight;
data[index + 0] = r;
data[index + 1] = g;
data[index + 2] = b;
data[index + 3] = 0;
}, row);
}, map.weights);
ctx |> putImageData(imageData, 0., 0., 0., 0., float_of_int(width), float_of_int(height));
}
},
render: _self => <canvas id="weight-map"
width={string_of_int(width)}
height={string_of_int(width)}
ref={_self.handle(setCanvasRef)}></canvas>
};
};
对于编译器而言,array('a)
与 Js.Typed_array.Uint8ClampedArray.t
不是同一类型,因此它们的操作(包括索引)不可互换。这与不能添加 int 和 float 的原则相同。
要设置类型化数组元素,您需要找到(或编写)允许您显式执行此操作的绑定,而不是使用索引运算符。为此,您可以查看 Js.Typed_array
模块——有一个 module type S
,我们可以将其表示为 'all typed array modules must conform to this module signature'。这包括 Js.Typed_array.Uint8ClampedArray
模块。所以你可以使用 S
模块类型的 unsafe_set
函数来设置类型化数组元素,因为 Js.Typed_array.Uint8ClampedArray
实现了它:
let module UI8s = Js.Typed_array.Uint8ClampedArray;
UI8s.unsafe_set(data, index, r);
UI8s.unsafe_set(data, index + 1, g);
UI8s.unsafe_set(data, index + 2, b);
UI8s.unsafe_set(data, index + 3, 0);
我正在尝试更新 Canvas 的图像上下文的 ImageData,当我尝试在数据数组中设置元素时,我收到一条错误消息,提示该数组的类型为 Js.Typed_array.Uint8ClampedArray.t
当有预期 array('a)
.
为什么我不能更新 JS TypedArray 实现?
这是我的组件代码(为清楚起见做了一些简化):
let make = _children => {
let map = FeatureMap.make(100, 100);
let (width, height) = map.dimensions;
{...component,
initialState: () => {
map: map,
canvasRef: ref(None)
},
didMount: self => switch (self.state.canvasRef^) {
| None => ()
| Some(canvas) => {
let ctx = getContext2d(canvas);
let imageData = createImageDataCoords(ctx, ~width=float_of_int(width), ~height=float_of_int(height));
let data = Webapi.Dom.Image.data(imageData);
Array.iteri((x, row) => {
Array.iteri((y, weight) => {
let index = (x * width + y) * 4;
let (r, g, b) = weight;
data[index + 0] = r;
data[index + 1] = g;
data[index + 2] = b;
data[index + 3] = 0;
}, row);
}, map.weights);
ctx |> putImageData(imageData, 0., 0., 0., 0., float_of_int(width), float_of_int(height));
}
},
render: _self => <canvas id="weight-map"
width={string_of_int(width)}
height={string_of_int(width)}
ref={_self.handle(setCanvasRef)}></canvas>
};
};
对于编译器而言,array('a)
与 Js.Typed_array.Uint8ClampedArray.t
不是同一类型,因此它们的操作(包括索引)不可互换。这与不能添加 int 和 float 的原则相同。
要设置类型化数组元素,您需要找到(或编写)允许您显式执行此操作的绑定,而不是使用索引运算符。为此,您可以查看 Js.Typed_array
模块——有一个 module type S
,我们可以将其表示为 'all typed array modules must conform to this module signature'。这包括 Js.Typed_array.Uint8ClampedArray
模块。所以你可以使用 S
模块类型的 unsafe_set
函数来设置类型化数组元素,因为 Js.Typed_array.Uint8ClampedArray
实现了它:
let module UI8s = Js.Typed_array.Uint8ClampedArray;
UI8s.unsafe_set(data, index, r);
UI8s.unsafe_set(data, index + 1, g);
UI8s.unsafe_set(data, index + 2, b);
UI8s.unsafe_set(data, index + 3, 0);