使用 React 创建图像放大镜

2025-06-04

使用 React 创建图像放大镜

今天,我们来创建一个简单的图像放大镜组件。

首先,让我们创建组件的基本结构。

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>
  );
}
Enter fullscreen mode Exit fullscreen mode

然后,我们需要添加一个控制放大镜显示的状态

 const [showMagnifier, setShowMagnifier] = useState(false);
Enter fullscreen mode Exit fullscreen mode

以及更新状态的事件处理程序。

...
    <img
        src={src}
        style={{ height: height, width: width }}
        onMouseEnter={(e) => {
          setShowMagnifier(true);
        }}
        onMouseLeave={() => {
          setShowMagnifier(false);
        }}
        alt={"img"}
      />

...
Enter fullscreen mode Exit fullscreen mode

现在,我们需要添加一个保存放大镜 x、y 位置的状态,并在鼠标悬停在图像上时更新它。

...
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]);
    }}
    ...
/>

Enter fullscreen mode Exit fullscreen mode

坐标pageX/Y相对于当前页面的左/上角。
pageXOffset/pageYOffset页面的滚动偏移量。
left/top图像左/上位置的坐标。

const x = e.pageX - left - window.pageXOffset;
const y = e.pageY - top - window.pageYOffset;
Enter fullscreen mode Exit fullscreen mode

这两个计算将根据图像为我们提供光标的 x/y 坐标。

为了计算放大镜的位置,我们还需要知道图像的像素大小,因此当鼠标进入图像时,让我们更新它。

<img
    ...
    onMouseEnter={(e) => {
          // update image size and turn-on magnifier
          const elem = e.currentTarget;
          const { width, height } = elem.getBoundingClientRect();
          setSize([width, height]);
          setShowMagnifier(true);
    }}
    ...
/>

Enter fullscreen mode Exit fullscreen mode

现在,我们可以为放大镜添加位置和其他基本样式。

<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",
    }}
/>

Enter fullscreen mode Exit fullscreen mode

然后,我们需要放大放大镜内的图像。

    ...
    //calculate zoomed image size
    backgroundSize: `${imgWidth * zoomLevel}px ${imgHeight * zoomLevel}px`,
    ...
Enter fullscreen mode Exit fullscreen mode

此外,我们需要根据图像上的光标位置将图像置于放大镜的中心。

    ...
    //calculate position of zoomed image.
    backgroundPositionX: `${-x * zoomLevel + magnifieWidth / 2}px`,
    backgroundPositionY: `${-y * zoomLevel + magnifierHeight / 2}px`
    ...
Enter fullscreen mode Exit fullscreen mode

我们成功了。以下是完整代码和演示:

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>
  );
}
Enter fullscreen mode Exit fullscreen mode

谢谢大家!

文章来源:https://dev.to/anxiny/create-an-image-magnifier-with-react-3fd7
PREV
参加工作面试时您应该知道的首字母缩略词。
NEXT
JavaScript 中的柯里化