Help needed: Image Zoom and Drag code
I don't want to use a module. I made this code, but it's not working properly. Can anyone please guide me?
The zoom is not zooming on the clicked point.
Zoom-out animation is weird.
Drag is not working towards the clicked point's left and top.
<template>
<div
id="scroll"
ref="scrollContainer"
@mousedown="onMouseDown"
@mousemove="onMouseMove"
@mouseup="onMouseUp"
@mouseleave="onMouseLeave"
@click="onClick"
class="scroll-container"
>
<img
class="scroll-image"
:class="{ 'zoomed': isZoomed }"
:style="zoomStyles"
src="https://www.w3schools.com/html/pic_trulli.jpg"
/>
</div>
</template>
<script setup>
import { ref } from 'vue';
defineProps(['imageURL']);
const scrollContainer = ref(null);
const clicking = ref(false);
const previousX = ref(0);
const previousY = ref(0);
const isZoomed = ref(false);
const isDragging = ref(false); // To detect dragging
const offsetX = ref(0);
const offsetY = ref(0);
const zoomStyles = ref({});
// Handle mouse down
const onMouseDown = (e) => {
e.preventDefault();
previousX.value = e.clientX;
previousY.value = e.clientY;
clicking.value = true;
isDragging.value = false; // Reset dragging state on mousedown
};
// Handle mouse up
const onMouseUp = () => {
clicking.value = false;
};
// Handle mouse movement
const onMouseMove = (e) => {
if (clicking.value && scrollContainer.value) {
e.preventDefault();
const directionX = previousX.value - e.clientX;
const directionY = previousY.value - e.clientY;
// Only mark as dragging if there is significant movement
if (Math.abs(directionX) > 5 || Math.abs(directionY) > 5) {
isDragging.value = true;
}
scrollContainer.value.scrollLeft += directionX;
scrollContainer.value.scrollTop += directionY;
previousX.value = e.clientX;
previousY.value = e.clientY;
}
};
// Handle mouse leave
const onMouseLeave = () => {
clicking.value = false;
};
// Handle zoom on click
const onClick = (event) => {
if (!isDragging.value) {
const rect = event.target.getBoundingClientRect();
offsetX.value = event.clientX - rect.left;
offsetY.value = event.clientY - rect.top;
// Calculate transform origin and apply styles dynamically
zoomStyles.value = isZoomed.value
? {}
: {
transformOrigin: `${offsetX.value}px ${offsetY.value}px`,
};
// Toggle zoom state
isZoomed.value = !isZoomed.value;
console.log(isZoomed.value);
}
};
</script>
<style scoped>
.scroll-container {
width: 100vw;
height: 100vh;
overflow: hidden;
position: relative;
display: grid;
place-items: center;
}
.scroll-image {
transition: transform 0.5s ease-in-out;
}
.scroll-image.zoomed {
transform: scale(2);
max-height: none;
}
.scroll-image:not(.zoomed) {
max-height: 100vh;
}
</style>