我正在尝试为画布项目制作放大镜,并且正在尝试制作一种模式,其中涉及将包含图像副本的画布部分复制到第二个较小的画布。我不断遇到错误,指出:
"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)
这是由图像加载的“异步性质”引起的一个相当经典的问题。我们看一下错误信息:
“无法在‘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)