Skip to content

How to magnify multiple elements on a canvas using the javascript magnifier

Essentially 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: = 'url("'+pRow.getValue("imgPath")+'")'; //pRow here refers to a parameter array that is passed in containing data about the image and rectangle = "no-repeat"; = 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.

If you require more information about the code I’ve written let me know.


Doing more research I’ve come up with the idea that it might be possible to draw 2 magnifiers on the screen. The top magnifier would draw the rectangle and since that is just a rectangle with empty space behind it, the magnifier should then draw the rectangle on top of the image that is being magnified as the magnified image is on the bottom magnifier.

I’ve yet to test this to see if it works as I expect or even possible to draw two magnifiers on screen like I plan. I will be trying to test this today. In the meantime could someone let me know if this will work or if there is another better way? Thanks for any assistance in solving how to do this.

Update 2:

Research into my idea has discovered an interesting mechanic. If I put in c.parentElement.insertBefore(c,glass) Nothing changes. BUT if I put in c.parentElement.insertBefore(glass, c) the magnifier is drawn BEHIND THE CANVAS! Therefore I believe if I draw a canvas on top of my existing one, draw the rectangle on it. Then using that line I could theoretically sandwich the magnifier between the rectangle and the image which would then do the desired behaviour without needing to magnify multiple elements.

Visual aid: So this is what’s currently happening Current example

This is what I want enter image description here

Update 3:

Turns out that I require the rectangle to be linked with the image location so that when you move the magnifier down, the rectangle is still correct relative to the magnification Here is a visual aid of the actual requirement when you move the magnifier: enter image description here

Update 4:

From discussion of this issue with my fellow workers, it might be possible to apparently draw the rectangle onto the master image that is being used to magnify. I have absolutely no idea how I would do so and nor do I know if the magnifier can pick up rectangle if I somehow learned how to drawn a rectangle onto the master image instead of the canvas image. to better explain here is a visual aid

enter image description here

enter image description here

My fellow employees seem to believe it is possible to somehow draw a rectangle on to that unscaled image so that the magnifier picks it up. I don’t know if Javascript knows how to do that and I don’t know if magnifier can even render the changes if they were implemented


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
    //   var mc = document.createElement("canvas")     // Create an offscreen canvas, put the image and then the bounding box
     var mc = document.getElementById('offscreenCanvas')     // Get an offscreen canvas.  saves from having to create it each time
     mc.width = imgwidth     // Make the canvas the same size as the master image.   Otherwise whatever we render will be truncated.
     mc.height = imgheight
     var mctx = mc.getContext("2d")     // Get the drawing context for this offscreen canvas
     mctx.clearRect(0,0,mc.width,mc.height)     // Erase the previous box (if any)
     mctx.drawImage(img,0,0,imgwidth,imgheight)     // Draw the full image onto our magnifier canvas, starting at (0,0)
     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
     var r_img = mc.toDataURL("image/png")     // Serialise the result of overlaying the box on the image
    //   window.location=r_img     // Debugging ... open image in a new window, "toDataURL() image")
     glass = document.getElementById("magnifier")     // Get pre-existing div for the magnifier = "url("+r_img+")"     // Our rendered image

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