Background
I have following code,
let canvas = document.getElementById("canvas");
let ctx = canvas.getContext("2d");
ctx.beginPath();
ctx.fillStyle = "#ff0000"; // red circle
ctx.arc(100, 100, 20, 0, 2*Math.PI, true);
ctx.fill()
I want to disable the usage of fillStyle
, strokeStyle
, etc of ctx
and add a new variable called buffer
to ctx
, e.g.
// a green circle will be drawn
ctx.beginPath();
ctx.fillStyle = "#00ff00"; // green circle
ctx.arc(100, 100, 20, 0, 2*Math.PI, true);
ctx.fill()
// after disabling the usage of fillStyle
// again, a green circle will be drawn, not a blue one
ctx.beginPath();
ctx.fillStyle = "#0000ff"; // blue one, but actually not work
ctx.arc(100, 100, 20, 0, 2*Math.PI, true);
ctx.fill()
// want to draw a blue one, must use buffer to change circle's color
ctx.buffer = "#0000ff"; // bn
ctx.beginPath();
ctx.fillStyle = "#0000ff" // actually not work
ctx.arc(100, 100, 20, 0, 2*Math.PI, true);
ctx.fill()
Solution
I searched a lot but hardly found useful solution.
- Inherit
CanvasRenderingContext2D
, it's not a good idea, here. Can't inherit from context object? - write a wrapper for context
class ContextWrapper{
constructor(ctx) {
this.raw_ctx = ctx
this._buffer = '#ffffff'
}
set fillStyle(val) {
// do nothing
}
set buffer(val) {
this._buffer = val;
this.raw_ctx.fillStyle = this._buffer;
}
//
}
// in this way, in order to use context's other methods, I have to call its wrapper first
// I don't like that, because it's ugly and inconvenient.
let wrapper = new ContextWrapper(ctx)
wrapper.raw_ctx.arc(100,100,20, 0, 2*Math.PI, true)
// another way, I write 'proxy method', like the code below,
// but I don't like it either, because there are so many methods to be re-implement here,
// a lot work need to be done.
class ContextWrapper{
//// ...
set fillStyle(val) {
// do nothing
}
set buffer(val) {
this._buffer = val;
this.raw_ctx.fillStyle = this._buffer;
}
arc(x, y, r, start, end, clockwise) {
this.raw_ctx.arc(x, y, r, start, end, clockwise)
}
// ...
}
Is there a smart way to implement my idea? for example,
let proxy = new Proxy(ctx);
// proxy.buffer indicates setter of buffer in proxy and change ctx.fillStyle in the meantime.
proxy.buffer = "#00ff00";
// proxy.beginPath() indicates ctx.beginPath()
proxy.beginPath();
// setter of fillStyle indicates proxy's fillStyle, it doesn't change ctx.fillStyle
proxy.fillStyle = "#0000ff";
// proxy.arc indicates ctx.arc
proxy.arc(100, 100, 20, 0, 2*Math.PI, true);
// proxy.fill() indicates ctx.fill()
proxy.fill()