我正在尝试修改canvas上下文对象的某些功能,而不必更改正在使用它的任何代码。通过创建Proxy
对象的解决方案已发布在此处:JS Proxying HTML5 canvas context。
我的问题是:通过使用Proxy
作为原型,是否可以在不依赖ctx
的情况下实现此行为?
像这样直接使用它
let acx = Object.create(ctx, {})
acx.fillStyle = 'red'
导致与链接的问题中所述相同的错误消息
TypeError: 'set fillStyle' called on an object that
does not implement interface CanvasRenderingContext2D.
关于我测试过的所有ctx方法。
在链接的问题中,这被解释为CanvasRenderingContext2DPrototype
而不是接受伪造的ctx对象。 accepting在这里到底是什么意思?有什么办法可以解决这个问题?
您可以存储画布上下文属性描述符,并重新定义所需的属性/方法。这是执行代理服务器工作的更复杂的方法。
var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
var prototype = Object.getPrototypeOf(ctx);
var descriptors = Object.getOwnPropertyDescriptors(prototype);
Object.defineProperties(prototype, {
fillStyle: {
get() {
console.log("Getting fillStyle");
return descriptors.fillStyle.get.call(this);
},
set(value) {
console.log("Setting fillStyle to", value);
descriptors.fillStyle.set.call(this, value);
}
},
fillRect: {
value(x, y, w, h) {
console.log("Drawing rectangle", x, y, w, h);
return descriptors.fillRect.value.call(this, x, y, w, h);
}
}
});
var canvas2 = document.querySelector("canvas");
var ctx2 = canvas2.getContext("2d");
ctx2.fillStyle = "red";
//>> Setting fillStyle to red
ctx2.fillRect(10, 10, 100, 100);
//>> Drawing rectangle 10 10 100 100
<canvas id="canvas"></canvas>