Hey there, future web wizard! Have you ever scrolled through images on your phone or tablet and wished you could do more than just swipe? Like, what if you could zoom in on a tiny detail, or drag the image around to see every corner? Well, guess what? You absolutely can, right in your web browser! And the best part? It’s not as hard as you might think.
Table of Contents
Today, we’re going to embark on an amazing project: building an image carousel that you can control with your fingers (or your mouse, if you’re on a computer!) using a cool JavaScript library called Hammer.js. We’ll learn how to add exciting features like touch-swiping to move between images, pinching to zoom in and out, and even dragging the zoomed image around. This is going to be a super fun way to make your websites truly interactive in 2025!
What is a Hammer.js Image Carousel Anyway?
Before we dive into the exciting world of code, let’s quickly understand what we’re building.
An image carousel is like a slideshow of pictures on a website. Instead of just seeing one picture, you can click buttons or swipe to see the next one. Think of it like flipping through a photo album, but on your screen!
Now, when we add Hammer.js to the mix, we make this carousel super interactive. Hammer.js is a fantastic little JavaScript library that helps us understand “touch gestures.” These are the things you do with your fingers on a touchscreen, like:
- Swiping: Sliding your finger across the screen to move to the next image.
- Pinching: Using two fingers to zoom in or out on an image.
- Panning (or dragging): Moving a zoomed-in image around with one finger to see different parts of it.
So, our Hammer.js image carousel will be a photo album that you can control with simple touch gestures, making it feel very natural and easy to use, just like your favorite apps!
Why Use Hammer.js for Our Image Carousel?
You might be thinking, “Can’t I do this with just plain JavaScript?” And the answer is, “Yes, you can!” But it would be much, much harder. Here’s why Hammer.js is our superhero for this image carousel project:
- Simplicity: Hammer.js makes it super easy to detect complex touch gestures. Without it, you’d have to write a lot of complicated code to figure out if someone is swiping, pinching, or panning. Hammer.js handles all that messy stuff for us!
- Cross-Browser Compatibility: It works well across different web browsers and devices, so your image carousel will look and feel great whether someone is using Chrome on an Android phone or Safari on an iPhone.
- Built for Touch: It’s specifically designed for touch interactions, making it perfect for creating mobile-friendly and intuitive web experiences.
Getting Started: The Basic Structure of Our Hammer.js Image Carousel
Every great project starts with a good foundation. For our Hammer.js image carousel, we’ll need three main parts:
- HTML (the skeleton): This is where we’ll set up the basic layout for our carousel and the places where our images will go.
- CSS (the style): This will make our carousel look nice and organized.
- JavaScript (the brain): This is where all the magic happens! We’ll use JavaScript, along with Hammer.js, to make our carousel interactive.
Step 1: Setting Up the HTML for Our Hammer.js Image Carousel
First, let’s create our index.html
file. This file will contain the basic structure of our web page. Don’t worry about understanding every single line right now; we’ll break it down.
HTML
<!DOCTYPE <strong>html</strong>>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Hammer.js Image Carousel with Controlled Dragging</title>
<script src="https://cdn.jsdelivr.net/npm/hammerjs@2.0.8/hammer.min.js"></script>
<style>
/* Our CSS will go here */
body {
margin: 0;
font-family: Arial, sans-serif;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100vh;
background-color: #f4f4f9;
}
.carousel {
width: 80%;
max-width: 600px;
overflow: hidden;
position: relative;
border: 2px solid #ddd;
border-radius: 8px;
background: #fff;
}
.slides {
display: flex;
transition: transform 0.5s ease-in-out;
}
.slide {
min-width: 100%;
height: 300px;
background-size: contain;
background-repeat: no-repeat;
background-position: center;
}
.buttons {
position: absolute;
top: 50%;
width: 100%;
display: flex;
justify-content: space-between;
transform: translateY(-50%);
}
.button {
background-color: rgba(0, 0, 0, 0.5);
color: white;
border: none;
padding: 10px 15px;
cursor: pointer;
border-radius: 50%;
}
.button:hover {
background-color: rgba(0, 0, 0, 0.8);
}
#upload-container {
margin-bottom: 20px;
}
#zoom-overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.8);
display: none; /* Hidden by default */
justify-content: center;
align-items: center;
z-index: 10;
overflow: hidden;
cursor: grab;
}
#zoom-overlay img {
transform-origin: center;
transition: transform 0.3s ease;
cursor: grab;
}
#zoom-overlay img:active {
cursor: grabbing;
}
</style>
</head>
<body>
<div id="upload-container">
<input type="file" id="imageUploader" multiple accept="image/*">
<button id="loadImages">Load Images</button>
</div>
<div class="carousel" id="carousel">
<div class="slides" id="slides">
</div>
<div class="buttons">
<button class="button" id="prev">‹</button>
<button class="button" id="next">›</button>
</div>
</div>
<div id="zoom-overlay">
<img id="zoom-image" src="" alt="Zoomed Image">
</div>
<script>
// All our JavaScript code for the Hammer.js image carousel will be here
</script>
</body>
</html>
Let’s break down this HTML for our Hammer.js image carousel:
<head>
section:<!DOCTYPE html>
and<html lang="en">
: These are standard beginnings for any HTML page.<meta charset="UTF-8">
: Tells the browser how to read characters.<meta name="viewport" content="width=device-width, initial-scale=1.0">
: Super important for making your website look good on phones and tablets! It tells the browser to set the width of the page to the device’s screen width.<title>Hammer.js Image Carousel with Controlled Dragging</title>
: This is what appears in your browser tab.<script src="https://cdn.jsdelivr.net/npm/hammerjs@2.0.8/hammer.min.js"></script>
: This is crucial! This line brings the Hammer.js library into our project. We’re getting it from a CDN (Content Delivery Network), which is like a super-fast server that hosts common libraries.<style>
tags: This is where we’ll put all our CSS code. It’s inside the HTML file for now to keep things simple, but in bigger projects, you’d put this in a separate.css
file.
<body>
section:<div id="upload-container">
: This is where we’ll have a button to upload our own images, making our image carousel truly customizable.<input type="file" id="imageUploader" multiple accept="image/*">
: This is a special input that lets you pick files.multiple
means you can pick more than one, andaccept="image/*"
means it will only show image files.<button id="loadImages">Load Images</button>
: A button to trigger loading the selected images.
<div class="carousel" id="carousel">
: This is the main container for our image carousel.<div class="slides" id="slides">
: Thisdiv
will hold all our individual images. We’ll add them here using JavaScript.<div class="buttons">
: Thisdiv
holds the “previous” and “next” buttons for our image carousel.<button class="button" id="prev">‹</button>
and<button class="button" id="next">›</button>
: Our navigation buttons.
<div id="zoom-overlay">
: This is a special “overlay” that will pop up when we want to zoom in on an image. It’s hidden (display: none;
) by default.<img id="zoom-image" src="" alt="Zoomed Image">
: This is where the zoomed-in image will be displayed.
<script>
tags: This is where we’ll write all our JavaScript code. This code will make our HTML elements move, respond to clicks and touches, and bring our Hammer.js image carousel to life!
Step 2: Styling Our Hammer.js Image Carousel with CSS
Our HTML is just the bare bones. Now, let’s add some style to make our Hammer.js image carousel look good! The CSS code is already inside the <style>
tags in the HTML from the previous step.
Let’s quickly go over what the CSS does for our Hammer.js image carousel:
body
: Centers everything on the page and sets a nice background color..carousel
: This is the main box for our carousel. It sets its size, adds a border, and makes sure anything that goes outside its boundaries is hidden (overflow: hidden
)..slides
: This is the container for all our images.display: flex
makes them line up next to each other.transition: transform 0.5s ease-in-out;
is important because it makes the slide movement smooth and not jumpy..slide
: Each individual image in the carousel.min-width: 100%
ensures each slide takes up the full width of the carousel.background-size: contain
makes sure the whole image fits without cropping, andbackground-position: center
centers the image..buttons
: Positions the navigation buttons on the left and right of the carousel..button
: Styles for the next/previous buttons – makes them round and semi-transparent.#upload-container
: Adds some space below the upload elements.#zoom-overlay
: This is the dark background that appears when you zoom in. It covers the whole screen (position: fixed
,width: 100%
,height: 100%
).display: none
keeps it hidden until we need it.#zoom-overlay img
: Styles the image inside the zoom overlay.transform-origin: center
is key for zooming, making the image zoom from its middle.transition: transform 0.3s ease;
makes the zoom animation smooth.#zoom-overlay img:active
: Changes the cursor when you’re dragging the zoomed image.
Step 3: Bringing Our Hammer.js Image Carousel to Life with JavaScript!
This is where the real fun begins! We’ll write JavaScript code to handle the image loading, carousel navigation, and, of course, the awesome touch gestures with Hammer.js for our image carousel.
The JavaScript code will go inside the <script>
tags at the very bottom of your <body>
section.
JavaScript
const slides = document.getElementById('slides');
const prevButton = document.getElementById('prev');
const nextButton = document.getElementById('next');
const imageUploader = document.getElementById('imageUploader');
const loadImagesButton = document.getElementById('loadImages');
const zoomOverlay = document.getElementById('zoom-overlay');
const zoomImage = document.getElementById('zoom-image');
let totalSlides = 0;
let currentIndex = 0;
// Variables for zoom and controlled drag
let scale = 1;
let posX = 0;
let posY = 0;
let startX = 0;
let startY = 0;
let isDragging = false;
// Function to update the slide position
function updateSlidePosition() {
slides.style.transform = `translateX(-${currentIndex * 100}%)`;
}
// Navigate to the previous slide
function goToPreviousSlide() {
if (currentIndex > 0) {
currentIndex--;
} else {
currentIndex = totalSlides - 1; // Wrap around to the last slide
}
updateSlidePosition();
}
// Navigate to the next slide
function goToNextSlide() {
if (currentIndex < totalSlides - 1) {
currentIndex++;
} else {
currentIndex = 0; // Wrap around to the first slide
}
updateSlidePosition();
}
// Load images into the carousel
function loadImages() {
const files = imageUploader.files;
if (files.length === 0) {
alert('Please select some images.');
return;
}
slides.innerHTML = ''; // Clear existing slides
totalSlides = files.length;
Array.from(files).forEach(file => {
const reader = new FileReader();
reader.onload = function (e) {
const slide = document.createElement('div');
slide.classList.add('slide');
slide.style.backgroundImage = `url('${e.target.result}')`;
slide.addEventListener('click', () => zoomImagePreview(e.target.result));
slides.appendChild(slide);
};
reader.readAsDataURL(file);
});
currentIndex = 0;
updateSlidePosition();
}
// Show the zoom overlay
function zoomImagePreview(src) {
zoomImage.src = src;
zoomOverlay.style.display = 'flex'; // Show the overlay
scale = 1; // Reset zoom
posX = 0; // Reset position
posY = 0;
updateZoom();
}
// Hide the zoom overlay
zoomOverlay.addEventListener('click', (e) => {
if (e.target === zoomOverlay) { // Only close if clicking on the background, not the image
zoomOverlay.style.display = 'none';
}
});
// Update zoom and position for the zoomed image
function updateZoom() {
zoomImage.style.transform = `translate(${posX}px, ${posY}px) scale(${scale})`;
}
// Handle mouse wheel for zooming
zoomOverlay.addEventListener('wheel', (e) => {
e.preventDefault(); // Stop the page from scrolling
scale += e.deltaY * -0.001; // Adjust zoom sensitivity
scale = Math.max(scale, 0.1); // Prevent negative or zero scale
updateZoom();
});
// Handle mouse drag to move the image (panning)
zoomImage.addEventListener('mousedown', (e) => {
isDragging = true;
startX = e.clientX - posX; // Calculate where the mouse clicked relative to the image's current position
startY = e.clientY - posY;
});
zoomOverlay.addEventListener('mousemove', (e) => {
if (!isDragging) return; // Only drag if the mouse button is down
posX = e.clientX - startX; // Calculate new position based on mouse movement
posY = e.clientY - startY;
updateZoom(); // Update the image's position as you move the mouse
});
zoomOverlay.addEventListener('mouseup', () => {
isDragging = false; // Stop dragging once mouse is released
});
zoomOverlay.addEventListener('mouseleave', () => {
isDragging = false; // Stop dragging if mouse leaves the zoom area
});
// Event listeners for our Hammer.js image carousel buttons and file input
prevButton.addEventListener('click', goToPreviousSlide);
nextButton.addEventListener('click', goToNextSlide);
loadImagesButton.addEventListener('click', loadImages);
// Set up Hammer.js for swipe gestures on the main carousel
const carousel = document.getElementById('carousel');
const hammer = new Hammer(carousel); // Tell Hammer.js to listen to our carousel
// Detect swipe gestures for the Hammer.js image carousel
hammer.on('swipeleft', goToNextSlide); // When swiped left, go to the next slide
hammer.on('swiperight', goToPreviousSlide); // When swiped right, go to the previous slide
// Set up Hammer.js for pinch and pan gestures on the zoom overlay image
const hammerZoom = new Hammer(zoomImage); // Tell Hammer.js to listen to our zoomed image
// Enable pinch and pan recognizers
hammerZoom.get('pinch').set({ enable: true });
hammerZoom.get('pan').set({ direction: Hammer.DIRECTION_ALL, enable: true });
let initialScale = 1; // To store the scale at the start of a pinch gesture
let initialPosX = 0; // To store the X position at the start of a pan gesture
let initialPosY = 0; // To store the Y position at the start of a pan gesture
hammerZoom.on('pinchstart', (e) => {
initialScale = scale; // Remember the current scale
});
hammerZoom.on('pinchmove', (e) => {
scale = initialScale * e.scale; // Update scale based on pinch movement
updateZoom();
});
hammerZoom.on('panstart', (e) => {
initialPosX = posX; // Remember the current X position
initialPosY = posY; // Remember the current Y position
});
hammerZoom.on('panmove', (e) => {
posX = initialPosX + e.deltaX; // Update X position based on pan movement
posY = initialPosY + e.deltaY; // Update Y position based on pan movement
updateZoom();
});
Let’s break down this JavaScript code for our Hammer.js image carousel step-by-step:
1. Getting Our Tools Ready (Variables and DOM Elements)
First, we grab all the important pieces from our HTML using document.getElementById()
. These are like our handles to control different parts of the page.
slides
,prevButton
,nextButton
, etc.: These are direct links to our HTML elements.totalSlides
,currentIndex
: These are simple numbers to keep track of how many images we have and which one we’re currently looking at in our image carousel.scale
,posX
,posY
,startX
,startY
,isDragging
: These variables are specifically for our zoom and pan feature. They help us remember how much we’ve zoomed, where the image is on the screen, and if we’re currently dragging it.
2. Making the Carousel Move
updateSlidePosition()
: This is a core function for our image carousel. It uses a CSS trick (transform: translateX()
) to shift theslides
container left or right, showing a different image.goToPreviousSlide()
andgoToNextSlide()
: These functions simply change thecurrentIndex
and then callupdateSlidePosition()
to show the correct image. They also make sure we “wrap around” to the beginning or end if we go past the last or first image.
3. Loading Our Own Images into the Hammer.js Image Carousel
loadImages()
: This function is triggered when you click the “Load Images” button.- It checks if you’ve selected any files.
slides.innerHTML = '';
: This clears out any old images in the carousel.- It then loops through each selected image file.
FileReader()
: This is a special tool in JavaScript that lets us read the contents of files on your computer (like images).reader.onload = function (e) { ... }
: When the reader finishes reading an image, this function runs. It creates a newdiv
for the slide, sets its background image to the loaded image, and adds it to ourslides
container.slide.addEventListener('click', () => zoomImagePreview(e.target.result));
: This is super important! It adds a click listener to each image in the carousel. When you click an image, it will call ourzoomImagePreview
function to open it in the zoom view.
4. The Amazing Zoom & Pan Feature
This is where things get really cool and where we add more interactivity to our Hammer.js image carousel!
zoomImagePreview(src)
: This function is called when you click an image in the carousel.- It sets the
src
of thezoomImage
element to the clicked image. zoomOverlay.style.display = 'flex';
: This makes the hidden zoom overlay appear!- It resets
scale
,posX
, andposY
so that each new image starts at its original size and position in the zoom view.
- It sets the
- Hiding the Zoom Overlay:
zoomOverlay.addEventListener('click', (e) => { ... });
: This listens for clicks on the zoom overlay. If you click on the dark background around the image (not the image itself), it will hide the overlay.
updateZoom()
: This function is very similar toupdateSlidePosition()
, but it applies thescale
,posX
, andposY
values to thezoomImage
. This makes the image zoom in/out and move around.- Mouse Wheel Zooming:
zoomOverlay.addEventListener('wheel', (e) => { ... });
: This listens for your mouse scroll wheel. When you scroll, it changes thescale
value and then callsupdateZoom()
to make the image bigger or smaller.e.preventDefault()
stops the whole page from scrolling when you’re trying to zoom.
- Mouse Dragging (Panning):
zoomImage.addEventListener('mousedown', ...)
: When you press your mouse button down on thezoomImage
, we setisDragging
totrue
and remember where you clicked (startX
,startY
).zoomOverlay.addEventListener('mousemove', ...)
: As long asisDragging
istrue
(meaning you’re holding the mouse button down and moving), we updateposX
andposY
based on how much you’ve moved the mouse. Then,updateZoom()
moves the image.zoomOverlay.addEventListener('mouseup', ...)
andzoomOverlay.addEventListener('mouseleave', ...)
: These setisDragging
tofalse
when you let go of the mouse button or move your mouse outside the zoom area, stopping the dragging.
5. Connecting Everything (Event Listeners)
prevButton.addEventListener('click', goToPreviousSlide);
: When the “previous” button is clicked, ourgoToPreviousSlide
function runs.nextButton.addEventListener('click', goToNextSlide);
: Same for the “next” button.loadImagesButton.addEventListener('click', loadImages);
: When the “Load Images” button is clicked, ourloadImages
function runs.
6. The Hammer.js Magic for Our Image Carousel!
Finally, the star of the show for touch gestures!
- For the Carousel Swiping:
const carousel = document.getElementById('carousel');
: We get a reference to our main carousel container.const hammer = new Hammer(carousel);
: This line is where we “activate” Hammer.js on ourcarousel
element. It tells Hammer.js to start listening for touch gestures on this specific part of our page.hammer.on('swipeleft', goToNextSlide);
: This is the magic! It says: “Hey Hammer.js, when you detect a ‘swipeleft’ gesture on thecarousel
, please run thegoToNextSlide
function.”hammer.on('swiperight', goToPreviousSlide);
: Similarly, for a right swipe, go to the previous slide.
- For the Zoom Overlay Pinch and Pan:
const hammerZoom = new Hammer(zoomImage);
: We create another Hammer.js instance, but this time, it listens to ourzoomImage
inside the overlay.hammerZoom.get('pinch').set({ enable: true });
: By default, some gestures in Hammer.js might be turned off. We explicitly enable thepinch
gesture for our zoom image.hammerZoom.get('pan').set({ direction: Hammer.DIRECTION_ALL, enable: true });
: We also enable thepan
gesture, allowing dragging in all directions.hammerZoom.on('pinchstart', ...)
andhammerZoom.on('pinchmove', ...)
: These handle the pinch-to-zoom.pinchstart
remembers the current zoom level, andpinchmove
calculates the new zoom level based on how much you’re pinching.hammerZoom.on('panstart', ...)
andhammerZoom.on('panmove', ...)
: These handle the pan (dragging) when zoomed in.panstart
remembers the image’s current position, andpanmove
updates it as you drag your finger.
Putting It All Together: Full Code for Your Hammer.js Image Carousel!
Now that you understand each piece, here’s the complete HTML and JavaScript code for your amazing Hammer.js Image Carousel with touch, zoom, and pan capabilities!
HTML
<!DOCTYPE <strong>html</strong>>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Amazing Hammer.js Project: Image Carousel with Touch, Zoom & Pan</title>
<script src="https://cdn.jsdelivr.net/npm/hammerjs@2.0.8/hammer.min.js"></script>
<style>
body {
margin: 0;
font-family: Arial, sans-serif;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100vh;
background-color: #f4f4f9;
overflow: hidden; /* Prevent body scroll when zoom overlay is active */
}
.carousel {
width: 80%;
max-width: 600px;
overflow: hidden;
position: relative;
border: 2px solid #ddd;
border-radius: 8px;
background: #fff;
}
.slides {
display: flex;
transition: transform 0.5s ease-in-out;
}
.slide {
min-width: 100%;
height: 300px;
background-size: contain;
background-repeat: no-repeat;
background-position: center;
cursor: pointer; /* Indicate that slides are clickable */
}
.buttons {
position: absolute;
top: 50%;
width: 100%;
display: flex;
justify-content: space-between;
transform: translateY(-50%);
z-index: 1; /* Ensure buttons are above slides */
}
.button {
background-color: rgba(0, 0, 0, 0.5);
color: white;
border: none;
padding: 10px 15px;
cursor: pointer;
border-radius: 50%;
font-size: 1.5em;
display: flex;
align-items: center;
justify-content: center;
width: 40px;
height: 40px;
margin: 0 10px;
}
.button:hover {
background-color: rgba(0, 0, 0, 0.8);
}
#upload-container {
margin-bottom: 20px;
display: flex;
gap: 10px;
align-items: center;
}
#upload-container input[type="file"] {
padding: 8px;
border: 1px solid #ccc;
border-radius: 4px;
}
#upload-container button {
background-color: #007bff;
color: white;
border: none;
padding: 10px 15px;
border-radius: 5px;
cursor: pointer;
font-size: 1em;
}
#upload-container button:hover {
background-color: #0056b3;
}
#zoom-overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.8);
display: none; /* Hidden by default */
justify-content: center;
align-items: center;
z-index: 10;
overflow: hidden;
cursor: grab;
}
#zoom-overlay img {
max-width: 90%;
max-height: 90%;
object-fit: contain; /* Ensure image fits within overlay */
transform-origin: center;
transition: transform 0.3s ease; /* Smooth transition for zoom */
cursor: grab;
}
#zoom-overlay img:active {
cursor: grabbing;
}
</style>
</head>
<body>
<div id="upload-container">
<input type="file" id="imageUploader" multiple accept="image/*">
<button id="loadImages">Load Images</button>
</div>
<div class="carousel" id="carousel">
<div class="slides" id="slides">
</div>
<div class="buttons">
<button class="button" id="prev">‹</button>
<button class="button" id="next">›</button>
</div>
</div>
<div id="zoom-overlay">
<img id="zoom-image" src="" alt="Zoomed Image">
</div>
<script>
const slides = document.getElementById('slides');
const prevButton = document.getElementById('prev');
const nextButton = document.getElementById('next');
const imageUploader = document.getElementById('imageUploader');
const loadImagesButton = document.getElementById('loadImages');
const zoomOverlay = document.getElementById('zoom-overlay');
const zoomImage = document.getElementById('zoom-image');
let totalSlides = 0;
let currentIndex = 0;
// Variables for zoom and controlled drag
let scale = 1;
let posX = 0;
let posY = 0;
let startX = 0;
let startY = 0;
let isDragging = false;
// Function to update the slide position for the Hammer.js image carousel
function updateSlidePosition() {
slides.style.transform = `translateX(-${currentIndex * 100}%)`;
}
// Navigate to the previous slide in the Hammer.js image carousel
function goToPreviousSlide() {
if (totalSlides === 0) return; // No slides to navigate
if (currentIndex > 0) {
currentIndex--;
} else {
currentIndex = totalSlides - 1; // Wrap around to the last slide
}
updateSlidePosition();
}
// Navigate to the next slide in the Hammer.js image carousel
function goToNextSlide() {
if (totalSlides === 0) return; // No slides to navigate
if (currentIndex < totalSlides - 1) {
currentIndex++;
} else {
currentIndex = 0; // Wrap around to the first slide
}
updateSlidePosition();
}
// Load images into the Hammer.js image carousel
function loadImages() {
const files = imageUploader.files;
if (files.length === 0) {
alert('Please select some images.');
return;
}
slides.innerHTML = ''; // Clear existing slides
totalSlides = files.length;
Array.from(files).forEach(file => {
const reader = new FileReader();
reader.onload = function (e) {
const slide = document.createElement('div');
slide.classList.add('slide');
slide.style.backgroundImage = `url('${e.target.result}')`;
slide.addEventListener('click', () => zoomImagePreview(e.target.result));
slides.appendChild(slide);
};
reader.readAsDataURL(file);
});
currentIndex = 0;
updateSlidePosition();
}
// Show the zoom overlay for the Hammer.js image carousel's zoom feature
function zoomImagePreview(src) {
zoomImage.src = src;
zoomOverlay.style.display = 'flex';
scale = 1;
posX = 0;
posY = 0;
updateZoom();
}
// Hide the zoom overlay
zoomOverlay.addEventListener('click', (e) => {
if (e.target === zoomOverlay) {
zoomOverlay.style.display = 'none';
}
});
// Update zoom and position for the zoomed image
function updateZoom() {
zoomImage.style.transform = `translate(${posX}px, ${posY}px) scale(${scale})`;
}
// Handle mouse wheel for zooming
zoomOverlay.addEventListener('wheel', (e) => {
e.preventDefault();
scale += e.deltaY * -0.001; // Adjust zoom sensitivity
scale = Math.max(scale, 0.1); // Prevent negative or zero scale
updateZoom();
});
// Handle mouse drag to move the image (without continuous panning)
zoomImage.addEventListener('mousedown', (e) => {
isDragging = true;
startX = e.clientX - posX;
startY = e.clientY - posY;
zoomImage.style.cursor = 'grabbing'; // Change cursor to grabbing
});
zoomOverlay.addEventListener('mousemove', (e) => {
if (!isDragging) return;
posX = e.clientX - startX;
posY = e.clientY - startY;
updateZoom();
});
zoomOverlay.addEventListener('mouseup', () => {
isDragging = false;
zoomImage.style.cursor = 'grab'; // Change cursor back to grab
});
zoomOverlay.addEventListener('mouseleave', () => {
isDragging = false;
zoomImage.style.cursor = 'grab'; // Change cursor back if mouse leaves
});
// Event listeners for our Hammer.js image carousel
prevButton.addEventListener('click', goToPreviousSlide);
nextButton.addEventListener('click', goToNextSlide);
loadImagesButton.addEventListener('click', loadImages);
// Set up Hammer.js for swipe gestures on the main carousel
const carousel = document.getElementById('carousel');
const hammer = new Hammer(carousel);
// Detect swipe gestures for the Hammer.js image carousel
hammer.on('swipeleft', goToNextSlide);
hammer.on('swiperight', goToPreviousSlide);
// Set up Hammer.js for pinch and pan gestures on the zoom overlay image
const hammerZoom = new Hammer(zoomImage);
// Enable pinch and pan recognizers
hammerZoom.get('pinch').set({ enable: true });
hammerZoom.get('pan').set({ direction: Hammer.DIRECTION_ALL, enable: true });
let initialScale = 1;
let initialPosX = 0;
let initialPosY = 0;
hammerZoom.on('pinchstart', (e) => {
initialScale = scale;
});
hammerZoom.on('pinchmove', (e) => {
scale = initialScale * e.scale;
updateZoom();
});
hammerZoom.on('panstart', (e) => {
initialPosX = posX;
initialPosY = posY;
});
hammerZoom.on('panmove', (e) => {
posX = initialPosX + e.deltaX;
posY = initialPosY + e.deltaY;
updateZoom();
});
</script>
</body>
</html>
Try It Out!
To see your amazing Hammer.js Image Carousel in action:
- Save the entire code above as an
index.html
file on your computer. - Open that
index.html
file in your web browser (like Chrome, Firefox, Safari, Edge). - Click the “Choose Files” button to select some images from your computer.
- Click “Load Images.”
- Now, try:
- Clicking the
‹
and›
buttons to navigate. - If you have a touchscreen, swipe left and right on the carousel to change images!
- Click on an image in the carousel to open the zoom view.
- In the zoom view, try scrolling your mouse wheel to zoom in and out.
- Click and drag the zoomed image to pan around it.
- If you have a touchscreen, try pinching to zoom and dragging with one finger to pan!
- Clicking the
You’ve just built a fantastic and interactive Hammer.js Image Carousel!
Conclusion
You did it! You’ve successfully built a powerful and interactive Hammer.js Image Carousel with touch, zoom, and pan features right in your browser. This project teaches you not only about basic web development (HTML, CSS, JavaScript) but also how to use an external library like Hammer.js to add advanced touch gestures. This skill is super valuable for making modern, mobile-friendly websites.
Keep experimenting, try adding more features (like deleting images, or a “download” button!), and don’t be afraid to break things and fix them. That’s how we learn best!
Did you find this post helpful for building your Hammer.js Image Carousel? Please let us know if you liked it or disliked it! Share this amazing project with your friends or on your social media to inspire others to build cool things!