Estoy intentando construir una lupa para una aplicación de visualización de lienzo cgm. Estoy tratando de dibujar el lienzo principal que contiene una imagen cgm en un lienzo más pequeño que se amplía para crear un efecto de zoom. Tengo un problema, sin embargo, al superponer correctamente el lienzo de zoom, parece estar en la esquina superior derecha. Quiero que el círculo contenga la parte del lienzo que está encima, excepto ampliada para hacer zoom.
Aquí hay un código de ejemplo para referencia
var canvas = document.getElementById("canvas1"); var ctx = canvas.getContext("2d"); var ox = canvas.width / 2; var oy = canvas.height / 2; ctx.font = "42px serif"; ctx.textAlign = "center"; ctx.textBaseline = "middle"; ctx.fillStyle = "#800"; ctx.fillRect(ox / 2, oy / 2, ox, oy); function magnify() { var canvas = document.getElementById("canvas1"); var ctx = canvas.getContext('2d') var base64 = canvas.toDataURL('image/png', 0); drawing = new Image(); drawing.onload = () => { var tcanvas = document.getElementById("tCanvas"); var ctx1 = tcanvas.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:#808080;"></canvas> <canvas id="canvas1" width=240 height=240 style="background-color:#808080;"></canvas> <p></p> <button id="magnify" onclick="magnify();">Zoom</button> ¿No está seguro de por qué está convirtiendo el lienzo en una URL de datos o por qué usa un patrón? Simplemente renderice el lienzo usando ctx.drawImage(
El siguiente ejemplo crea una copia del lienzo para hacer zoom y luego representa la imagen ampliada en el lienzo izquierdo (recortada a un círculo) y el original a la derecha con un círculo que representa el área ampliada.
Mueva el mouse sobre la imagen derecha para hacer zoom.
canvas1.addEventListener("mousemove",mouseEvents); const mouse = {x : 0, y : 0}; function mouseEvents(e){ const bounds = canvas1.getBoundingClientRect(); mouse.x = e.pageX - bounds.left - scrollX; mouse.y = e.pageY - bounds.top - scrollY; magnifyImage(mouse.x, mouse.y, 2, imageToZoom, tCanvas, canvas1); } const tag = (tag, props = {}) => Object.assign(document.createElement(tag), props); function copyImage(image) { const can = tag("canvas", {width: image.width, height: image.height}); can.getContext("2d").drawImage(image, 0, 0); return can; } const ctx = canvas1.getContext("2d"); const w = canvas1.width; const h = canvas1.height; ctx.fillStyle = "#800"; ctx.fillRect(w * 0.2, h * 0.2, w * 0.6, h * 0.6); ctx.fillStyle = "#850"; ctx.fillRect(w * 0.3, h * 0.3, w * 0.4, h * 0.4); const imageToZoom = copyImage(canvas1); magnifyImage(60, 60, 2, imageToZoom, tCanvas, canvas1); function magnifyImage(magCenterX, magCenterY, zoom, src, destZoom, destCircle) { const w = src.width / zoom | 0; const h = src.height / zoom | 0; // draw source image with circle var ctx = destCircle.getContext("2d"); ctx.clearRect(0, 0, destCircle.width, destCircle.height); ctx.drawImage(src, 0, 0); ctx.strokeStyle = "#FA0"; ctx.lineWidth = 3; ctx.beginPath(); ctx.arc(magCenterX, magCenterY, Math.max(w, h) / 2, 0, Math.PI * 2); ctx.stroke(); // draw zoomed content ctx = destZoom.getContext("2d"); ctx.clearRect(0, 0, destZoom.width, destZoom.height); ctx.drawImage( src, magCenterX - w / 2, magCenterY - h / 2, w, h, 0, 0, destZoom.width, destZoom.height ); // clip zoomed image ctx.globalCompositeOperation = "destination-in"; ctx.beginPath(); ctx.arc( destZoom.width / 2, destZoom.height / 2, Math.max(destZoom.width, destZoom.height ) / 2, 0, Math.PI * 2 ); ctx.fill(); ctx.globalCompositeOperation = "source-over"; }; <canvas id="tCanvas" width=240 height=240 style="background-color:#808080;"></canvas> <canvas id="canvas1" width=240 height=240 style="background-color:#808080;"></canvas> <p>Mouse over right image to zoom</p>