Create an Image Magnifier with React
Today, let's create a simple image magnifier component.
First, let's create the basic structure of the component.
function ImageMagnifier({ src, width, height, magnifierHeight = 100, magnifieWidth = 100, zoomLevel = 1.5}: { src: string; width?: string; height?: string; magnifierHeight?: number; magnifieWidth?: number; zoomLevel?: number;}) { return ( // the container <div style={{ position: "relative", height: height, width: width }} > // the image <img src={src} style={{ height: height, width: width }} alt={"img"} /> // a div for the magnifier <div></div> </div> );}
Then, we need to add a state that controll the display of magnifier
const [showMagnifier, setShowMagnifier] = useState(false);
and, the event handler that update the state.
... <img src={src} style={{ height: height, width: width }} onMouseEnter={(e) => { setShowMagnifier(true); }} onMouseLeave={() => { setShowMagnifier(false); }} alt={"img"} />...
Now, we need to add a state that holds x, y position of magnifier, and update it when mouse move hover the image.
...const [[x, y], setXY] = useState([0, 0]);...<img ... onMouseMove={(e) => { // update cursor position const elem = e.currentTarget; const { top, left } = elem.getBoundingClientRect(); // calculate cursor position on the image const x = e.pageX - left - window.pageXOffset; const y = e.pageY - top - window.pageYOffset; setXY([x, y]); }} .../>
The pageX/Y
coordinates are relative to the left/top corner of current page.
The pageXOffset/pageYOffset
are the scroll offsets of the page.
The left/top
are the coordinates of the image left/top position.
const x = e.pageX - left - window.pageXOffset;const y = e.pageY - top - window.pageYOffset;
These two calculations will give us the cursor's x/y coordinates based on the image.
In order to calculate the position of the magnifier, we also need to have the size of image in pixels, so let's update it when mouse is entering the image.
<img ... onMouseEnter={(e) => { // update image size and turn-on magnifier const elem = e.currentTarget; const { width, height } = elem.getBoundingClientRect(); setSize([width, height]); setShowMagnifier(true); }} .../>
Now, we can add the position and other basic styles to the magnifier.
<div style={{ display: showMagnifier ? "" : "none", position: "absolute", // prevent magnifier blocks the mousemove event of img pointerEvents: "none", // set size of magnifier height: `${magnifierHeight}px`, width: `${magnifieWidth}px`, // move element center to cursor pos top: `${y - magnifierHeight / 2}px`, left: `${x - magnifieWidth / 2}px`, opacity: "1", // reduce opacity so you can verify position border: "1px solid lightgray", // show the border of magnifier backgroundColor: "white", backgroundImage: `url('${src}')`, backgroundRepeat: "no-repeat", }}/>
Then, we need to zoom the image inside the magnifier.
... //calculate zoomed image size backgroundSize: `${imgWidth * zoomLevel}px ${imgHeight * zoomLevel}px`, ...
Also, we need to center the image in the magnifier base on cursor position on the image.
... //calculate position of zoomed image. backgroundPositionX: `${-x * zoomLevel + magnifieWidth / 2}px`, backgroundPositionY: `${-y * zoomLevel + magnifierHeight / 2}px` ...
We done it. Here is the full code and a demo:
function ImageMagnifier({ src, width, height, magnifierHeight = 100, magnifieWidth = 100, zoomLevel = 1.5}: { src: string; width?: string; height?: string; magnifierHeight?: number; magnifieWidth?: number; zoomLevel?: number;}) { const [[x, y], setXY] = useState([0, 0]); const [[imgWidth, imgHeight], setSize] = useState([0, 0]); const [showMagnifier, setShowMagnifier] = useState(false); return ( <div style={{ position: "relative", height: height, width: width }} > <img src={src} style={{ height: height, width: width }} onMouseEnter={(e) => { // update image size and turn-on magnifier const elem = e.currentTarget; const { width, height } = elem.getBoundingClientRect(); setSize([width, height]); setShowMagnifier(true); }} onMouseMove={(e) => { // update cursor position const elem = e.currentTarget; const { top, left } = elem.getBoundingClientRect(); // calculate cursor position on the image const x = e.pageX - left - window.pageXOffset; const y = e.pageY - top - window.pageYOffset; setXY([x, y]); }} onMouseLeave={() => { // close magnifier setShowMagnifier(false); }} alt={"img"} /> <div style={{ display: showMagnifier ? "" : "none", position: "absolute", // prevent magnifier blocks the mousemove event of img pointerEvents: "none", // set size of magnifier height: `${magnifierHeight}px`, width: `${magnifieWidth}px`, // move element center to cursor pos top: `${y - magnifierHeight / 2}px`, left: `${x - magnifieWidth / 2}px`, opacity: "1", // reduce opacity so you can verify position border: "1px solid lightgray", backgroundColor: "white", backgroundImage: `url('${src}')`, backgroundRepeat: "no-repeat", //calculate zoomed image size backgroundSize: `${imgWidth * zoomLevel}px ${ imgHeight * zoomLevel }px`, //calculate position of zoomed image. backgroundPositionX: `${-x * zoomLevel + magnifieWidth / 2}px`, backgroundPositionY: `${-y * zoomLevel + magnifierHeight / 2}px` }} ></div> </div> );}
Thank you all!
Original Link: https://dev.to/anxinyang/create-an-image-magnifier-with-react-3fd7
Dev To
An online community for sharing and discovering great ideas, having debates, and making friendsMore About this Source Visit Dev To