javascript - JS 代理 HTML5 Canvas 上下文

标签 javascript html canvas ecmascript-6 es6-proxy

我希望代理 Canvas API,这样我就可以测试抽象方法是否确实绘制到 Canvas 上,但是我遇到了代理后出现错误的问题:

在未实现接口(interface) CanvasRenderingContext2D 的对象上调用的“strokeStyle”setter

此代码已简化但会引发相同的错误:

/** !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 方法来修复此错误:

set(target, property, value, receiver) {
    target[property] = value;
}

这个错误的原因可能看起来有点奇怪。 CanvasRenderingContext2D 实例没有自己的 strokeStyle 属性。相反,CanvasRenderingContext2DPrototype(每个 CanvasRenderingContext2D 实例的原型(prototype))有一个访问器属性,其set/get 组件将设置和获取实例的 stroke-style 值:

> ctx.hasOwnProperty("strokeStyle")
false

> Object.getOwnPropertyDescriptor(ctx.__proto__, "strokeStyle")
Object { get: strokeStyle(), set: strokeStyle(), enumerable: true, configurable: true }

(如果您有兴趣了解有关此模式的更多信息,请查看我在 JSON.parse not erroring on cyclic objects 上的回答。)

这里的问题是提供给 CanvasRenderingContext2DPrototype.strokeStyle setter 的 thisproxy 对象,而不是实际的 ctx 对象。也就是说,当我们仅在代理上设置属性时:

proxy.isAFake = true;

并在重新定义的 setter 中测试它:

Object.defineProperty(ctx.__proto__, "strokeStyle", {
    set: function() {
        console.log("strokeStyle setter called for proxy?", this.isAFake);
    }
});

我们看到 setter 记录了 proxy-only 属性:strokeStyle setter called for proxy?是的

无论出于何种原因,CanvasRenderingContext2DPrototype.strokeStyle 上的 setter 将只接受真正的 CanvasRenderingContext2D 实例,而不是代理实例。

关于javascript - JS 代理 HTML5 Canvas 上下文,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33804653/

相关文章:

javascript - 根据对象内数字的接近程度减少数组

jquery - 同一行问题上的多层div

r - 通过 exams2canvas 导入的 Canvas 测验缺少解决方案 Material /答案反馈

javascript - HTML5 Canvas 能够在绘制图像后放大/缩小吗?

javascript - jQuery .prepend() 不工作

javascript - 即使在调整大小时形成多行, float div 也应保持垂直居中。如何?

javascript - JSON是字符串吗?

javascript - navigator.clipboard.readText() 在 Firefox 中不起作用

javascript - 如何验证动态生成的包含 jquery 中的引导选项卡的表单

javascript - 如何从 Canvas 数据创建图像?