Skip to content
Advertisement

How can I magnify multiple elements on a canvas using the JavaScript magnifier?

I have a web page that displays an image excerpt from a document using drawimage(x,z,width,height). The user has the ability to draw a rectangle around any given line on the image by clicking the line. The image then has a rectangle drawn on it using rect(x,y,w,h).

Using the JavaScript magnifier, the user can hover over the image to see a zoomed in version. However, it does not show the rectangle drawn on to the image on the canvas.

Is it possible to draw both the rectangle and the image? Currently this is the setup for the magnifier:

//  - Setup the magnifier component
var  glass, w, h, bw;
glass = document.getElementById("magnifier");     // Get pre-existing div for the magnifier
glass.setAttribute("class", "img-magnifier-glass");

// Set background properties for the magnifier glass:
glass.style.backgroundImage = 'url("' + pRow.getValue("imgPath") + '")'; // pRow here refers to a parameter array that is passed in containing data about the image and rectangle
glass.style.backgroundRepeat = "no-repeat";
glass.style.backgroundSize = imgwidth + "px " + imgheight + "px";
     bw = 3;     // Border width of the magnifier glass.
     w = glass.offsetWidth / 2;
     h = glass.offsetHeight / 2;

Later on there is code to actually move the background position. But I don’t see a way to show the rectangle that is drawn on top of the image, in the canvas, on the magnifier.

Advertisement

Answer

Finally I have solved it and this one was quite the task.

To do it

  • I had to draw an offscreen canvas
  • Then on this new canvas copy the current master image and draw on a rectangle
  • Serialise the result in a URL
  • Then pass this URL to the magnifier background image property

This does introduce a long load time each time you want to change the rectangle location. But allows for the rectangle to become part of the image so the magnifier picks it up.

Here is the code (this was done in Omnis Studio if anything looks off from normal JavaScript (also there is a lot of code before this. But this is the solution, so I’ll just show this bit)):

// Draw the same orange box, but on the original image size
var img = document.getElementById('jp')  // The master image. It will
                                         // have been already loaded by now

// Create an offscreen canvas, put the image and then the bounding box
//var mc = document.createElement("canvas")

// Get an offscreen canvas. Saves from having to create it each time
var mc = document.getElementById('offscreenCanvas')

// Make the canvas the same size as the master image.
// Otherwise, whatever we render will be truncated.
mc.width = imgwidth
mc.height = imgheight

// Get the drawing context for this offscreen canvas
var mctx = mc.getContext("2d")

// Erase the previous box (if any)
mctx.clearRect(0, 0, mc.width, mc.height)

// Draw the full image onto our magnifier canvas, starting at (0, 0)
mctx.drawImage(img, 0, 0, imgwidth, imgheight)

mctx.beginPath()     // Create our selection box
mctx.strokeStyle = "orange"//
mctx.lineWidth = 8     // Because we're "zoomed in", make this line a little thicker
boxX = pRow.getValue("x")     // Top left x coordinate - unscaled coordinates
boxY = pRow.getValue("y")     // top left y coordinate
boxW = pRow.getValue("width")     // Distance right
boxH = pRow.getValue("height")     // Distance down
mctx.rect(boxX, boxY, boxW, boxH)
mctx.stroke()

// Serialise the result of overlaying the box on the image
var r_img = mc.toDataURL("image/png")
//   window.location = r_img     // Debugging ... open image in a new
                                 // window window.open(r_img, "toDataURL() image")

// Get pre-existing div for the magnifier
glass = document.getElementById("magnifier")

// Our rendered image
glass.style.backgroundImage = "url(" + r_img + ")"

If anyone can find a way to do this without needing to constantly reload the image and cause a large amount of lag/wait time. Please let me know.

Advertisement