1

我正在尝试更新 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>
    };
};
4

1 回答 1

3

对于编译器来说, anarray('a)与 a 的类型不同Js.Typed_array.Uint8ClampedArray.t,因此它们的操作(包括索引)是不可互换的。这与您不能添加 int 和 float 的原理相同。

要设置类型化数组元素,您需要找到(或编写)一个允许您显式执行此操作的绑定,而不是使用索引运算符。为此,您可以查看Js.Typed_array模块——module type S我们可以理解为“所有类型化数组模块必须符合此模块签名”。这包括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);
于 2019-03-16T21:54:39.590 回答