Why my handleMouseMove function is not working properly? I am trying to add zoom on hovering of image. It seems calculation is wrong, I need help how it is working, how to write it correctly. Trying to get the same effect as in amazon when you hover product , it show you little bit closer product. In my case it doesnt works. Please help, thank you
import React, { useState } from 'react';
const Index = () => {
const [hero, setHero] = useState('/img.jpg');
const handleImageClick = (src) => {
setHero(src);
const magnifier = document.getElementById('magnifier');
magnifier.style.backgroundImage = `url(${src})`;
};
const handleMouseMove = (e) => {
const magnifier = document.getElementById('magnifier');
const detailImage = document.getElementById('detailImage');
const rect = detailImage.getBoundingClientRect();
const x = e.clientX - rect.left;
const y = e.clientY - rect.top;
const offsetX = magnifier.offsetWidth / 2;
const offsetY = magnifier.offsetHeight / 2;
magnifier.style.backgroundPosition = `-${(x * 2) - offsetX}px -${(y * 2) - offsetY}px`;
magnifier.style.left = `${x - offsetX}px`;
magnifier.style.top = `${y - offsetY}px`;
};
return (
<>
<div className="col-11 col-md-4 bg-light border p-3 rounded-3">
<div className="zoom-container">
<div
id="detailImage"
className="detail-image"
onMouseMove={handleMouseMove}
onMouseLeave={() => {
const magnifier = document.getElementById('magnifier');
magnifier.style.display = 'none';
}}
onMouseEnter={() => {
const magnifier = document.getElementById('magnifier');
magnifier.style.display = 'block';
}}
>
<img
id="mainImage"
src={hero}
className="border zoom-image"
alt="card"
/>
<div id="magnifier" className="magnifier"></div>
</div>
</div>
<div className="mt-3 d-flex justify-content-between">
<img
src="/img.jpg"
className="border"
style={{ position: 'relative', width: '31%' }}
alt="card1"
onClick={() => handleImageClick('/img.jpg')}
/>
<img
src="/img.jpg"
className="border"
style={{ position: 'relative', width: '31%' }}
alt="card2"
onClick={() => handleImageClick('/img1.jpg')}
/>
<img
src="/img.jpg"
className="border"
style={{ position: 'relative', width: '31%' }}
alt="card3"
onClick={() => handleImageClick('/img2.jpg')}
/>
</div>
</div>
</div>
<style>{`
.zoom-container {
position: relative;
width: 100%;
}
.detail-image {
position: relative;
}
.zoom-image {
width: 100%;
}
.magnifier {
position: absolute;
border: 3px solid #000;
border-radius: 50%;
cursor: none;
width: 100px;
height: 100px;
display: none;
background-repeat: no-repeat;
background-size: 200%;
}
`}</style>
</>
);
};
export default Index;
2
Answers
Change
backgroundPosition
calculation to:First, I multiply the actual image width by a
scaler
to get the zoomed image width. Then, its position must bescaler
times negative of actual coordinates plus half size of the magnifier circle.I also check a few conditions to overcome a kind of overflow problem. With this block, the magnifying circle will always be inside the container unless it is very large.
Finally, I recommend you not to hide cursor but show it like this.
Demo