继承表单html5 canvas类

时间:2018-03-24 12:53:59

标签: javascript html5 canvas

我想在Javascript中定义我的自定义Canvas2D类,它来自原生的html5 canvas对象。我尝试用原型继承而不是经典方式来做这件事:

function Canvas2D(){
    var parent = document.createElement("canvas");

    var child = Object.create(parent);        
    child.getContext = function(){
        return parent.getContext('2d');
    };
    return child;
}

所以我可以用这种方式创建和使用对象实例

var canvas = new Canvas2D();
var context = canvas.getContext();

但是,当我尝试获取html5原生的width属性时:

var width = canvas.width;

我的浏览器抛出Uncaught TypeError: Illegal invocation异常。难道这个属性也不应该继承吗?我想这个问题与一些" get或set"限制或是某种访问修饰符对html5本机画布对象中属性的限制。

当我尝试使用自定义画布的实例作为参数调用drawImage时:

canvas.getContext().drawImage(new Canvas2D(), 300, 150);

浏览器抛出另一个异常 - Uncaught TypeError: Failed to execute 'drawImage' on 'CanvasRenderingContext2D': The provided value is not of type '(CSSImageValue or HTMLImageElement or SVGImageElement or HTMLVideoElement or HTMLCanvasElement or ImageBitmap or OffscreenCanvas)'

换句话说,浏览器抱怨我传递给drawImage方法的Canvas2D对象的类型,虽然我的画布是HTMLCanvasElement类型!我们可以使用以下行轻松查看:

console.log(new Canvas2D() instanceof HTMLCanvasElement);

在我的浏览器中打印出true

所以我的问题是:

1)有人可以解释“宽度”错误行为背后的原因吗?财产,我该如何解决?

2)我怎样才能强制drawImage将我的类识别为HTMLCanvasElement?

1 个答案:

答案 0 :(得分:2)

你可能不会。值得一提的是,HTMLCanvasElement(以及其他HTMLXY-s)也是一个接口,这意味着实际实现可能包含的细节根本不会出现在JavaScript级别上。就像画布一样,肯定有一个后备缓冲区,你根本看不到它。因此,制作副本的预期成功至少是值得怀疑的。

尝试一对简单的



console.log(document.createElement("canvas").width);
console.log(Object.create(document.createElement("canvas")).width);




已经表明它无法创建真正的HTMLCanvasElement。事实上,Object.create()甚至没有那么努力:

  
      
  1. 如果Type(O)不是Object或Null则抛出TypeError异常。
  2.   
  3. 让obj成为创建新对象的结果,就好像通过表达式new Object(),其中Object是具有该名称的标准内置构造函数
  4.   
  5. 将obj的[[Prototype]]内部属性设置为O。
  6.   
  7. 如果参数Properties存在且未定义,则将自己的属性添加到obj,就好像通过调用带有参数obj和Properties的标准内置函数Object.defineProperties一样。
  8.   
  9. 返回obj。
  10.   

new Object()尝试更加困难,它指定 主机对象 (HTMLXY-s)也被考虑在内:

  

1.a.i如果值是本机ECMAScript对象,请不要创建新对象,只需返回值。
  1.a.ii如果值是主机对象,则执行操作并以依赖于实现的方式返回结果,该方式可能取决于主机对象。

使用new Object测试您的代码:



function Canvas2D(){
    var parent = document.createElement("canvas");

    var child = new Object(parent);        
    child.getContext = function(){
        return parent.getContext('2d');
    };
    console.log(parent===child);
    return child;
}

var cnv=new Canvas2D();
console.log(cnv.width);
var ctx=cnv.getContext();




它得到了正确的width(默认为300),但有一些可疑的东西" copy" (请参阅检查child===parent,结果为true,暗示没有创建新对象,并且getContext的无限递归 - 至少在Chrome中 - 建议相同)。这里和现在我不知道它是1.ai(不应该是这种情况,画布或HTMLCanvasElement不是ECMA / JavaScript的一部分),或1.a.ii(遇到主机对象时依赖于实现的行为) ),但它无法确定。并且不期望:开头提到的,JavaScript级别的复制构造函数"无法了解实际实现对象的浏览器级细节。