如何扩展CanvasRenderingContext2D(如果可能的话,在ES6样式的脚本中)

时间:2016-03-30 04:44:12

标签: javascript canvas ecmascript-6

我想创建一个扩展CanvasRenderingContext2D的新类。这样我就可以将用户定义的属性分配给该新类的prototype属性,而不是CanvasRenderingContext2D.attribute。以下是我打算编写的代码:

class WL_CRC2D extends CanvasRenderingContext2D{
    constructor(){
        super();
    }
    setStyle(args){//...
    }
    //...
}

var ctx = new WL_CRC2D() // Uncaught TypeError: Illegal constructor

这不起作用,因为CanvasRenderingContext2D会阻止new运算符 - 就像下面的代码也会抛出错误一样:

var ctx = new CanvasRenderingContext2D(); // Uncaught TypeError: Illegal constructor

然后我尝试用另一种方式重写构造函数:

 class WL_CRC2D{
    constructor(){
        let ctxTemp = Object.create(CanvasRenderingContext2D.prototype);
        for (let i of Reflect.ownKeys(ctxTemp.__proto__)){
            Object.defineProperty(this.__proto__, i, Object.getOwnPropertyDescriptor(ctxTemp.__proto__, i));
        }
    }
    setStyle(args){//...
    }
    //...
}

var ctx = new WL_CRC2D(); // fine
console.log(ctx.arc); // function arc() { [native code] }
ctx.arc(0, 0, 10, 0, 1, true); // Uncaught TypeError: Illegal invocation

正如评论所示,以这种方式从WL_CRC2D创建的新实例实际上无法访问WL_CRC2D.prototype中的属性。

那么有没有办法绕过系统定义的CanvasRenderingContext2D类?请指教。谢谢!

1 个答案:

答案 0 :(得分:0)

我可能用丑陋的方式想出来了:

class WL_CanvasRenderingContext2D{
    constructor(ctx){
        this.ctx = ctx;
    }
}
(() => {
    var context = document.createElement('canvas').getContext('2d');
    for (let i of Reflect.ownKeys(Object.getPrototypeOf(ctx))){
        if (['symbol', 'constructor'].indexOf(typeof i) < 0){
            var propertyDesc = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(context), i);
            if (typeof context[i] != 'function'){
                [propertyDesc.get, propertyDesc.set] = [function(){return this.ctx[i]}, function(val){this.ctx[i] = val;}];
            }
            else{
                propertyDesc.value = function(...args) {this.ctx[i].apply(this.ctx, args)};
            }
            Object.defineProperty(WL_CanvasRenderingContext2D.prototype, i, propertyDesc);
        }
    }
})();

var a = new WL_CanvasRenderingContext2D(ctx);

如果上述代码存在任何缺陷,请通知我。谢谢!