Categories
Graphics JavaScript Web development

Magnify images with a draggable loupe

In a previous post we’ve seen how to create a magnifying glass effect with canvas. But the position of the lens was static, and of course in a useful application a user must be able to move the lens to a point of interest.

Static image of magnifying glass. Hang on for interactive version.

Draggable Vue component

To that end we’ll create a Vue component that works as a draggable loupe. The loupe hovers over an image that is likely to be downscaled (otherwise a magnifying glass is not of much use). Furthermore, we allow the image to be responsive. This means the position of the loupe in CSS pixels will not correspond to the image pixels. Since SVG elements may have their own coordinate system, let’s use SVG for the draggable, and make its coordinates match the underlying image.

HTML
CrossHairs.vue

The coordinate system can be set by the parent via the viewBox property. In this way we can make the position of the loupe match with the image coordinates.

We’ll implement the draggable with GreenSock’s Draggable:

JS
CrossHairs.vue

Single source of truth

The draggable passes the change in position (deltaX and deltaY) to the parent while the user drags. The parent component then adds these deltas to the current position after which the transform property of the CrossHairs component reacts to the updated position. Usually gsap’s Draggable manages the transform property (when using type: "x,y"), but here that property is overwritten when the parent component changes position. This guarantees the Single source of truth remains by the parent component.

Now let’s turn to the parent component.

Canvas lasagne

The CanvasScrutinizer component consists of several layers. First we have a canvas to which we copy our source image. This canvas will also determine the dimensions of the container div, since the other layers are positioned absolutely. The second canvas is for drawing the magnified part of the image. Top it off with the CrossHairs component to allow the user to move the loupe.

HTML
CanvasScrutinizer.vue

The script part of CanvasScrutinizer.vue is loosely based on the technique explained in the previous post. You can check it out on CodeSandbox, along with the app.

The loupe at work

See the application with UI (set magnification factor, set loupe size, image file input) at work in the lab.

Preview of the finished application