Estoy tratando de hacer una lupa para un proyecto de lienzo y estoy tratando de hacer un patrón que implique copiar parte del lienzo que contiene la copia de la imagen en un segundo lienzo más pequeño. Sigo encontrándome con un error que dice:
"Failed to execute 'createPattern' on 'CanvasRenderingContext2D': The image argument is a canvas element with a width or height of 0."Aquí hay un ejemplo del código:
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 eg 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() };Este es un problema bastante clásico causado por la 'naturaleza asíncrona' de la carga de imágenes. Echemos un vistazo al mensaje de error:
"Error al ejecutar 'createPattern' en 'CanvasRenderingContext2D': el argumento de la imagen es un elemento de lienzo con un ancho o alto de 0".
Dice que la altura o el ancho del objeto enviado al método createPattern() es cero, pero ¿por qué debería suceder eso?
Retrocedamos un poco en su código.
El objeto en cuestión es tileCanvas y su ancho y alto se determinan aquí:
tileCanvas.width = 2 * size tileCanvas.height = 2 * size Entonces, ¿cuál es el valor del size ? Retroceder un poco más revela
let size = w / 4 y w a su vez es
let w = drawing.naturalWidth cual es el quid de la cuestión. naturalWidth es una propiedad de un objeto de imagen, drawing en su caso. El problema es que lo está llamando justo después de completar su propiedad .src . En este momento, es posible que la imagen no se haya cargado por completo, por lo que devuelve cero.
Debe esperar a que la imagen se cargue por completo hasta consultar sus propiedades. Esto se hace escuchando el evento onload .
Aquí hay un ejemplo:
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 eg 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>