'Failed to execute 'createPattern' on 'CanvasRenderingContext2D': The image argument is a canvas element with a width or height of 0
I'm trying to make a loupe for a canvas project and I'm trying to make a pattern that involves copying part of the canvas that contains the image copy to a second, smaller, canvas. I keep running into a error stating:
"Failed to execute 'createPattern' on 'CanvasRenderingContext2D': The image argument is
a canvas element with a width or height of 0."
Here is an example of the code:
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>
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()
};
Solution 1:[1]
This is a rather classic problem caused by the 'asynchronous nature' of image loading. Let's take a look at the error message:
"Failed to execute 'createPattern' on 'CanvasRenderingContext2D': The image argument is a canvas element with a width or height of 0."
It says that either the height or the width of the object sent to the createPattern()
method is zero but why should that happen?
Let's step back in your code a little.
The object in question is tileCanvas
and it's width and height is determined here:
tileCanvas.width = 2 * size
tileCanvas.height = 2 * size
So what's the value of size
? Stepping back a bit further reveals
let size = w / 4
and w
in turn is
let w = drawing.naturalWidth
which is the crux of the matter. naturalWidth
is a property of an image object - drawing
in your case. The problem is that you're calling it right after populating it's .src
property. At this point in time the image might not have been completely loaded, thus it returns zero.
You must wait for the image to be fully loaded until querying it's properties. This is done by listening to the onload
event.
Here's an example:
var canvas = document.getElementById("canvas1");
var ctx = canvas.getContext('2d')
var base64 = canvas.toDataURL('image/png', 0);
drawing = new Image();
drawing.onload = () => {
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()
}
drawing.src = base64; // can also be a remote URL e.g. http://
<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>
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | obscure |