It is surprisingly easy to manipulate images in the browser using the html5 element
canvas. For instance, we can cut out part of the image and paste it back at another positon, in the mean time changing the shape or color of it.
And it doesn’t have to be rectangles only! Let’s create an example where we take a circular area of a downscaled image, then paste it back magnified. In effect a hand-lens or magnifying glass. A usefull tool!
In the Codepen above you see the original image on the left. An intermediate canvas containing a fragment of the image in the middle. And on the right the canvas containing a copy of the original image with the pasted artwork.
Let’s see how it’s done.
The original and its copy
First we get a reference to the original image, and we store its dimensions. Note that the image is downscaled and we store the actual width and height of the image, not the width and height as it is shown on the page. This image of hazel is 1,400px × 2,277px, so there is plenty of room for magnification.
Now copy the image to the canvas, using
Properties of magnification
Define the size of the loupe, the magnification factor and calculate the radius needed of the fragment of the original so that magnified it fills the whole magnifying glass.
We also position the (center of) the loupe. Here
py are hard coded somewhat arbitrarily. Wouldn’t it be nice if a user could determine the position of the loupe? We’ll come to that in this post!
Create a pattern
We’re copying part of the canvas that contains the image copy to a second, smaller, canvas. Again we’re using
drawImage, but now with nine arguments. Apart from the source canvas image it instructs the
drawImage function which source rectangle to render on what destination rectangle. See the MDN Web Docs for the possible parameters.
Next a pattern is created based on this intermediate canvas, and the pattern will be used for
fill on the main canvas.
Positioning the pattern
If we now fill a shape, the position of the pattern is determined by the coordinate system. It starts at the origin, so if we want the pattern to start at a specific point (as we do) we should transform the rendering context to set the new origin.
This moves the origin of the context to the left top of the (rectangular) area we want to draw our filled circle in. Relative to the new origin, the center of the circle is
(size, size). The third parameter of
arc below determines the radius of the circle and is also
And that’s it!
Alternative with clipping
I suppose you could reach the same result without the intermediate canvas and a pattern.
drawImage is quite a flexible tool and you can draw (part of) a canvas on itself.
Also, we can exclude parts of the canvas from being drawn on by using
clip, to fill a circular shape rather than a rectangle. It might we worth trying that out! Use this pen (shown above) as a starting point.
Actually, the follow-up post does use clipping to draw circular shapes, instead of a pattern.