0

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.

  1. Inherit CanvasRenderingContext2D, it's not a good idea, here. Can't inherit from context object?
  2. 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() 
Coneain
  • 198
  • 12

0 Answers0