0

I am trying to modify some functionality of the canvas context object without having to alter any code that is using this. A solution for this by creating a Proxy object has been posted here: JS Proxying HTML5 canvas context.

My question is: Can this behaviour be achieved without relying on Proxy by using ctx as a prototype?

Directly using it like this

let acx = Object.create(ctx, {})
acx.fillStyle = 'red'

results in the same Error messages as mentioned in the linked question

TypeError: 'set fillStyle' called on an object that
    does not implement interface CanvasRenderingContext2D.

on all ctx methods I've tested.

In the linked question this is explained as CanvasRenderingContext2DPrototype not accepting the fake ctx object. What exactly does accepting mean here? Is there any way to fix this?

Syntac
  • 1,687
  • 11
  • 10

1 Answers1

0

You can store the canvas context property descriptors, and redefine the properties/methods you want. this is a more complicated way of doing pretty much what a Proxy does.

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>
sney2002
  • 856
  • 3
  • 6