Zoom an image
Written byPhuoc Nguyen
Category
Level 3 — Advanced
Created
18 Apr, 2020
Last updated
07 May, 2021
In this post, we'll see how to create an image zoomer which allows users to zoom an image using a range slider. Here is the structure of the elements:
<!-- The image container -->
<div class="image-container">
<img id="image" />
</div>
<!-- The range slider -->
<div>
<!-- The minimum zoom level -->
<div>10%</div>
<!-- The slider is constructed by three parts -->
<div>
<div class="left"></div>
<div id="knob"></div>
<div class="right"></div>
</div>
<!-- The maximum zoom level -->
<div>200%</div>
</div>
#Prepare the image container
The image will be displayed at the center of its container. In case users zoom in the image to the level which makes the image bigger than its container, then we'll hide the outside parts.
Having that imagination, the container could be styled as below:
.image-container {
/* Center the content */
align-items: center;
display: flex;
justify-content: center;
overflow: hidden;
width: 100%;
}
#Calculate the initial scale
Initially, we want the image to be fit within its container. To do that, we clone the image and handle the
`load`
event to determine the size of image:// Query the element
const image = document.getElementById('image');
// Create new image element
const cloneImage = new Image();
cloneImage.addEventListener('load', function (e) {
// Get the natural size
const width = e.target.naturalWidth;
const height = e.target.naturalHeight;
// Set the size for image
image.style.width = `${width}px`;
image.style.height = `${height}px`;
});
// Clone it
cloneImage.src = image.src;
The initial scale can be determined based on the widths of container and image:
cloneImage.addEventListener('load', function(e) {
...
// The initial scale
const scale = image.parentNode.getBoundingClientRect().width / width;
});
Now we scale the image to that value by setting the
`transform`
style:cloneImage.addEventListener('load', function(e) {
...
image.style.transform = `scale(${scale}, ${scale})`;
});
#Create the range slider
You can take a look at the Create a range slider post for more details. Initially, we want to set the slider range based on the scale calculated in the previous section.
First, we define the minimum and maximum scales and calculate the range step:
const minScale = 0.1;
const maxScale = 2;
const step = (maxScale - minScale) / 100;
It's also possible to set the lower and upper values based on the initial scale. I set constant values to make this post simple
The slider can update the value via the width of left part:
// Query the elements
const knob = document.getElementById('knob');
const leftSide = knob.previousElementSibling;
cloneImage.addEventListener('load', function(e) {
...
leftSide.style.width = `${(scale - minScale) / step}%`;
});
#Scale the image when sliding the range
In the previous section, we set the initial value for the slider based on the scale. It's the time to do the other part, update the scale based on the slider's value.
It happens when user drags the knob:
const mouseMoveHandler = function (e) {
// Calculate the width for the left part
// ...
let newLeftWidth = ((leftWidth + dx) * 100) / containerWidth;
// Set the width
leftSide.style.width = `${newLeftWidth}%`;
// Calculate the scale
const scale = minScale + newLeftWidth * step;
image.style.transform = `scale(${scale}, ${scale})`;
};
Enjoy the demo!
Photo by Pedro Lastra on Unsplash
#Demo
#See also
Questions? 🙋
Do you have any questions? Not just about this specific post, but about any topic in front-end development that you'd like to learn more about? If so, feel free to send me a message on Twitter or send me an email. You can find them at the bottom of this page.
I have a long list of upcoming posts, but your questions or ideas for the next one will be my top priority. Let's learn together! Sharing knowledge is the best way to grow 🥷.
Recent posts ⚡
Copy the content of an element to your clipboard
01 Oct, 2023
Make a text area fit its content automatically
30 Sep, 2023
Quickly insert alternate characters while typing
30 Sep, 2023
Zebra-like background
30 Sep, 2023
Add autocomplete to your text area
28 Sep, 2023
Linear scale of a number between two ranges
28 Sep, 2023
Highlight the current line in a text area
27 Sep, 2023
Create your own custom cursor in a text area
27 Sep, 2023
Mirror a text area for improving user experience
26 Sep, 2023
Display the line numbers in a text area
24 Sep, 2023
Select a given line in a text area
24 Sep, 2023
Newsletter 🔔
If you're into front-end technologies and you want to see more of the content I'm creating, then you might want to consider subscribing to my newsletter.
By subscribing, you'll be the first to know about new articles, products, and exclusive promotions.
Don't worry, I won't spam you. And if you ever change your mind, you can unsubscribe at any time.
Phước Nguyễn