如何设置类型化对象的属性,同时保留它的类型?

时间:2016-05-11 18:52:29

标签: javascript canvas purescript putimagedata

我有一个特定的案例,但我一般也很好奇。

我有一个画布,我使用createImageData获取它的ImgData,并且我将它的数据属性设置为其他东西,然后使用PutImageData并将此修改后的ImgData传递给它。

我的PureScript版本失败,尽管在控制台中使用Javascript编写逻辑可以完美无缺地工作。 错误是:

foreign.js:423 Uncaught TypeError: Failed to execute 'putImageData' on 'CanvasRenderingContext2D': 
parameter 1 is not of type 'ImageData'.

在PureScript中:

getCleanBuffer :: forall e. Context2D -> Eff (canvas :: Canvas | e) ImageData
getCleanBuffer ctx = do
  imgData <- getImageData ctx 0.0 0.0 160.0 144.0
  return imgData { data = buffer }
 where buffer = asUint8ClampedArray $ A.replicate (160*144*4) 0

在控制台中编写此javascript(arr为160 * 144 * 4零)

var arr2 = new Uint8ClampedArray(arr);
var imgData = ctx.getImageData(0,0,160,144);
imgData.data = arr2;
ctx.putImageData(imgData,0,0);

我调试了getCleanBuffer,这是我发现的内容

var getCleanBuffer = function (ctx) {
var buffer = Data_TypedArray.asUint8ClampedArray(Data_Array.replicate((160 * 144 | 0) * 4 | 0)(0));
return function __do() {
    var v = Graphics_Canvas.getImageData(ctx)(0.0)(0.0)(160.0)(144.0)();
    var $9 = {};
    for (var $10 in v) {
        if (v.hasOwnProperty($10)) {
            $9[$10] = v[$10];
        };
    };
    $9.data = buffer;
    return $9;

这个$ 9(带有修改数据的ImgData副本)变量在检查时显示不是ImgData类型,就像v(原始的ImgData)那样,但它只是一个&#39; Object&#39 ;。 它缺少v的宽度和高度,但即使我在调试期间修复它,我仍然会得到同样的错误。

我认为问题在于新对象是无类型记录。宽度和高度未被复制的事实是另一个问题。

我可以编写一个javascript函数来手动设置数据属性。 但总的来说,这种情况似乎很常见,我肯定错过了一些东西,不是吗?

谢谢!

2 个答案:

答案 0 :(得分:3)

在这种情况下,ImageData的类型不正确,它是记录的类型同义词,但将JavaScript类类型值视为记录是不安全的,原因完全在于您在这里发现。

我已经按照菲尔的建议开了a bug report

对于一般情况,这是镜头派上用场的地方。您定义了_data :: LensP ImageData Uint8ClampedArray之类的镜头,然后可以执行imgData # _data %~ buffer以获得类似于更新语法的内容。

答案 1 :(得分:0)

我根本不知道purescript,所以我不会回答你问题的标题,但对于你的确切情况,这不是你应该如何创建一个&#34; 干净的ImageData &#34;

不同的浏览器具有ImageData对象的不同实现,并且由于specs仅需要"TypedArray"作为data属性,因此您无法确定每个UA(related Q/A)中此缓冲区的类型应为Uint8ClampedArray。 (现在living specs确实将此TypedArray的类型指定为Uint8ClampedArray。)

但幸运的是,当canvas API已经有context2D.createImageData(width, height)方法或 check-supported-browsers {{1}时,您似乎正在尝试重新发明轮子。 }如果您位于workerImageData(Uint8ClampedArray)不可用)

,则为构造函数

所以只需使用它,它就可以在支持canvas API的任何UA中使用,而且你不必担心复制任何类型。