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: stri…


This content originally appeared on DEV Community and was authored by AnxinYang

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!


This content originally appeared on DEV Community and was authored by AnxinYang


Print Share Comment Cite Upload Translate
APA
AnxinYang | Sciencx (2022-10-01T05:38:21+00:00) » Create an Image Magnifier with React. Retrieved from https://www.scien.cx/2021/05/02/create-an-image-magnifier-with-react/.
MLA
" » Create an Image Magnifier with React." AnxinYang | Sciencx - Sunday May 2, 2021, https://www.scien.cx/2021/05/02/create-an-image-magnifier-with-react/
HARVARD
AnxinYang | Sciencx Sunday May 2, 2021 » Create an Image Magnifier with React., viewed 2022-10-01T05:38:21+00:00,<https://www.scien.cx/2021/05/02/create-an-image-magnifier-with-react/>
VANCOUVER
AnxinYang | Sciencx - » Create an Image Magnifier with React. [Internet]. [Accessed 2022-10-01T05:38:21+00:00]. Available from: https://www.scien.cx/2021/05/02/create-an-image-magnifier-with-react/
CHICAGO
" » Create an Image Magnifier with React." AnxinYang | Sciencx - Accessed 2022-10-01T05:38:21+00:00. https://www.scien.cx/2021/05/02/create-an-image-magnifier-with-react/
IEEE
" » Create an Image Magnifier with React." AnxinYang | Sciencx [Online]. Available: https://www.scien.cx/2021/05/02/create-an-image-magnifier-with-react/. [Accessed: 2022-10-01T05:38:21+00:00]
rf:citation
» Create an Image Magnifier with React | AnxinYang | Sciencx | https://www.scien.cx/2021/05/02/create-an-image-magnifier-with-react/ | 2022-10-01T05:38:21+00:00
https://github.com/addpipe/simple-recorderjs-demo