JS代理HTML5画布上下文 [英] JS Proxying HTML5 canvas context
问题描述
我希望代理canvas API,以便我可以测试抽象方法是否确实可以绘制到画布上,但是我遇到的问题是,在proxing后出现错误:
I'm hoping to proxy the canvas API so I can test that abstracted methods do actually draw to the canvas, however I'm hitting issues where after proxing I get an error:
'strokeStyle'setter
此代码经过简化,但会引发相同的错误:
This code is simplified but throws the same error:
/** !NB: This snippet will probably only run in Firefox */
var canvas = document.createElement("canvas");
canvas.width = 100;
canvas.height = 100;
canvas.style.backgroundColor = '#FF0000';
var ctx = canvas.getContext("2d");
var calls = [];
var handler = {
get( target, property, receiver ) {
if ( typeof ctx[property] === 'function' ){
return function( ...args ){
calls.push( { call: property, args: args } )
return ctx[property]( ...args );
};
}
return ctx[property];
}
};
try {
document.body.appendChild(canvas);
var proxy = new Proxy( ctx, handler );
proxy.scale( 1, 1 );
proxy.strokeStyle = '#000000';
canvas.getContext = function(){
return proxy;
};
}
catch( e ) {
document.getElementById('message').innerHTML = 'Error: ' + e.message;
}
<div id="message"></div>
有什么想法吗?
推荐答案
您可以通过在处理程序上定义 set
方法来解决此错误:
You can fix this erro by defining a set
method on your handler:
set(target, property, value, receiver) {
target[property] = value;
}
此错误的原因似乎有点奇怪. CanvasRenderingContext2D
实例没有自己的 strokeStyle
属性.相反, CanvasRenderingContext2DPrototype
(每个 CanvasRenderingContext2D
实例的原型)具有访问器属性,其 set
/ get
组件将设置并获取实例的笔触样式值:
The reason for this error might seem a bit strange. CanvasRenderingContext2D
instances don't have their own strokeStyle
property. Instead, the CanvasRenderingContext2DPrototype
(the prototype of every CanvasRenderingContext2D
instance) has an accessor property whose set
/get
components will set and get the stroke-style value for the instance:
> ctx.hasOwnProperty("strokeStyle")
false
> Object.getOwnPropertyDescriptor(ctx.__proto__, "strokeStyle")
Object { get: strokeStyle(), set: strokeStyle(), enumerable: true, configurable: true }
((如果您有兴趣了解有关此模式的更多信息,请查看我对 JSON.parse的回答,不会在循环中出错)对象.)
(If you're interested in learning more about this pattern, have a look at my answer on JSON.parse not erroring on cyclic objects.)
这里的问题是提供给 CanvasRenderingContext2DPrototype.strokeStyle
设置器的 this
是 proxy
对象,而不是实际的 ctx
对象.也就是说,当我们仅在代理服务器上设置属性时:
The problem here is that the this
supplied to the CanvasRenderingContext2DPrototype.strokeStyle
setter is the proxy
object, not the actual ctx
object. That is, when we set a property on the proxy only:
proxy.isAFake = true;
并在重新定义的设置器中对其进行测试:
and test for it in a redefined setter:
Object.defineProperty(ctx.__proto__, "strokeStyle", {
set: function() {
console.log("strokeStyle setter called for proxy?", this.isAFake);
}
});
我们看到设置器记录了仅代理属性: strokeStyle设置器调用了代理吗?是
.
We see the setter logs the proxy-only property: strokeStyle setter called for proxy? true
.
无论出于何种原因, CanvasRenderingContext2DPrototype.strokeStyle
上的设置器将仅接受真正的 CanvasRenderingContext2D
实例,而不接受代理实例.
For whatever reason, the setter on CanvasRenderingContext2DPrototype.strokeStyle
will accept only a genuine CanvasRenderingContext2D
instance, not a proxied one.
这篇关于JS代理HTML5画布上下文的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!