'Trying to make a magnifying glass for html canvas that views cgm images
I'm attempting to build a loupe for a cgm canvas viewing application. I am trying to draw the main canvas containing a cgm image onto a smaller canvas that is blown up to create a zoom effect. I'm having an issue however overlaying the zoom canvas correctly it seems to be in the upper right corner. I want the circle to contain the part of tha canvas its over except enlarged to zoom.
Here is some example code for reference
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 e.g. 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>
Solution 1:[1]
Zoom on canvas
Not sure why you are converting the canvas to a data URL or why you use a pattern? Just render the canvas using ctx.drawImage(
Example
The example below creates a copy of the canvas to zoom, and then renders the zoomed image on the left canvas (clipped to a circle) and the original on the right with a circle representing the zoomed area.
Move mouse over right image to 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>
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 | Blindman67 |