如何在保留类型的同时设置类型化对象的 属性?
How to set a property of a typed object while retaining it's type?
我有一个具体案例,但我也很好奇。
我有一个 canvas,我使用 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 = {};
for (var in v) {
if (v.hasOwnProperty()) {
[] = v[];
};
};
.data = buffer;
return ;
这个 $9(带有修改数据的 ImgData 副本)变量在检查时显示不是 ImgData 类型,就像 v(原始 ImgData)一样,但它只是一个 'Object'。
它缺少 v 拥有的宽度和高度,但即使我在调试期间修复它,我仍然会遇到同样的错误。
我认为问题在于新对象是无类型记录。没有复制宽高是另外一个问题
我可以写一个javascript函数来手动设置数据属性。
但总的来说,这种情况似乎很常见,我肯定错过了什么,不是吗?
谢谢!
在这种情况下,ImageData
的类型不正确,它是记录的类型同义词,但是将 JavaScript class 类型的值准确地视为记录是不安全的您在这里发现的原因。
我已经按照 Phil 的建议打开了 a bug report。
对于一般情况,这是镜头派上用场的地方。你会定义一个像 _data :: LensP ImageData Uint8ClampedArray
这样的镜头,然后可以做 imgData # _data %~ buffer
来实现类似于更新语法的东西。
我根本不知道 purescript,所以我不会回答你的问题的标题,但对于你的具体情况,这不是你应该如何创建一个“clean ImageData".
不同的浏览器有不同的实现 ImageData
Object and since specs only required a "TypedArray" as the data
property, you can't be sure that the type of this buffer should be an Uint8ClampedArray
in every UA (related Q/A). (now living specs 请将此 TypedArray
的类型指定为 Uint8ClampedArray
)。
但幸运的是,当 canvas API 已经有一个 context2D.createImageData(width, height)
method, or a check-supported-browsers ImageData(Uint8ClampedArray)
Constructor if your are in worker(其中 createImageData
不可用时,您似乎正在尝试重新发明轮子)
所以只要使用它,它就可以在任何支持 canvas API 的 UA 中工作,而且你不必担心复制任何类型。
我有一个具体案例,但我也很好奇。
我有一个 canvas,我使用 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 = {};
for (var in v) {
if (v.hasOwnProperty()) {
[] = v[];
};
};
.data = buffer;
return ;
这个 $9(带有修改数据的 ImgData 副本)变量在检查时显示不是 ImgData 类型,就像 v(原始 ImgData)一样,但它只是一个 'Object'。 它缺少 v 拥有的宽度和高度,但即使我在调试期间修复它,我仍然会遇到同样的错误。
我认为问题在于新对象是无类型记录。没有复制宽高是另外一个问题
我可以写一个javascript函数来手动设置数据属性。 但总的来说,这种情况似乎很常见,我肯定错过了什么,不是吗?
谢谢!
在这种情况下,ImageData
的类型不正确,它是记录的类型同义词,但是将 JavaScript class 类型的值准确地视为记录是不安全的您在这里发现的原因。
我已经按照 Phil 的建议打开了 a bug report。
对于一般情况,这是镜头派上用场的地方。你会定义一个像 _data :: LensP ImageData Uint8ClampedArray
这样的镜头,然后可以做 imgData # _data %~ buffer
来实现类似于更新语法的东西。
我根本不知道 purescript,所以我不会回答你的问题的标题,但对于你的具体情况,这不是你应该如何创建一个“clean ImageData".
不同的浏览器有不同的实现 ImageData
Object and since specs only required a "TypedArray" as the data
property, you can't be sure that the type of this buffer should be an Uint8ClampedArray
in every UA (related Q/A). (now living specs 请将此 TypedArray
的类型指定为 Uint8ClampedArray
)。
但幸运的是,当 canvas API 已经有一个 context2D.createImageData(width, height)
method, or a check-supported-browsers ImageData(Uint8ClampedArray)
Constructor if your are in worker(其中 createImageData
不可用时,您似乎正在尝试重新发明轮子)
所以只要使用它,它就可以在任何支持 canvas API 的 UA 中工作,而且你不必担心复制任何类型。