JS代理HTML5画布上下文 [英] JS Proxying HTML5 canvas context

查看:60
本文介绍了JS代理HTML5画布上下文的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我希望代理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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆