无法在“CanvasRenderingContext2D”上执行“createPattern”:图像参数是宽度或高度为 0 的画布元素

2 javascript html5-canvas

我正在尝试为画布项目制作放大镜,并且正在尝试制作一种模式,其中涉及将包含图像副本的画布部分复制到第二个较小的画布。我不断遇到错误,指出:

"Failed to execute 'createPattern' on 'CanvasRenderingContext2D': The image argument is 
 a canvas element with a width or height of 0."
Run Code Online (Sandbox Code Playgroud)

这是代码示例:

HTML:

<canvas id="tCanvas" width=240 height=240 style="background-color:aqua;">
</canvas>
<canvas id="canvas1" width=240 height=240 style="background-color:#808080;">
</canvas>
<p></p>
<button id="download"   onclick="magnify();">Zoom</button>
Run Code Online (Sandbox Code Playgroud)

JS:

    var canvas = document.getElementById("canvas1");
    var ctx = canvas.getContext('2d')
    var base64 = canvas.toDataURL('image/png', 0);
    drawing = new Image();
    drawing.src = base64; // can also be a remote URL e.g. http://
    var canvas1 = document.getElementById("tCanvas");
    var ctx1 = canvas1.getContext('2d');
    ctx1.drawImage(drawing, 0, 0);
    let w = drawing.naturalWidth
    let h = drawing.naturalHeight
    let size = w / 4 // Size (radius) of magnifying glass
    let magnification = 2
    let r = size / magnification // Radius of part we want to magnify
    
    let px = w / 3.5
    let py = h / 4

     let tileCanvas = document.getElementById("tCanvas")
     tileCanvas.width = 2 * size
     tileCanvas.height = 2 * size
    
      tileCanvas.getContext('2d').drawImage(canvas, px - r, py - r, 2 * r, 2 * r, 0, 0, 2 * size, 2 * size)
    
      let pattern = ctx.createPattern(tileCanvas, "repeat")
    
      ctx.fillStyle = pattern
   
     ctx.translate(px - size, py - size)

    ctx.beginPath()
    ctx.arc(size, size, size, 0, 2 * Math.PI)
    ctx.fill()
    ctx.strokeStyle = "orangered"
    ctx.lineWidth = 12
    ctx.stroke()
};
Run Code Online (Sandbox Code Playgroud)

obs*_*ure 6

这是由图像加载的“异步性质”引起的一个相当经典的问题。我们看一下错误信息:

“无法在‘CanvasRenderingContext2D’上执行‘createPattern’:图像参数是宽度或高度为 0 的画布元素。”

它说发送到该方法的对象的高度或宽度createPattern()为零,但为什么会发生这种情况呢?

让我们稍微回顾一下您的代码。

有问题的对象是tileCanvas,它的宽度和高度在这里确定:

 tileCanvas.width = 2 * size
 tileCanvas.height = 2 * size
Run Code Online (Sandbox Code Playgroud)

那么 的价值是什么呢size?退一步进一步揭示

let size = w / 4
Run Code Online (Sandbox Code Playgroud)

w反过来又是

let w = drawing.naturalWidth
Run Code Online (Sandbox Code Playgroud)

这才是问题的关键。naturalWidth是图像对象的属性 -drawing在您的情况下。问题是您在填充它的.src属性后立即调用它。此时图像可能尚未完全加载,因此它返回零。

您必须等待图像完全加载,然后才能查询其属性。这是通过监听onload事件来完成的。

这是一个例子:

 tileCanvas.width = 2 * size
 tileCanvas.height = 2 * size
Run Code Online (Sandbox Code Playgroud)
let size = w / 4
Run Code Online (Sandbox Code Playgroud)