You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React实现图片悬停放大镜效果同时支持onLoad与onError事件的问题

解决方案

方案1:基于现有react-image-magnifiers组件扩展(无需更换组件)

GlassMagnifier 本身没有暴露onError事件,我们可以通过提前预加载图片的方式自行处理加载成功/失败逻辑,再决定是否渲染放大镜组件,完全复用原有圆形放大镜效果:

import { GlassMagnifier } from "react-image-magnifiers";
import { useState, useEffect, memo } from "react";

export const Image = memo(({imgSrc = "https://some-link"}) => {
    const [loadState, setLoadState] = useState('loading'); // 可选值loading/success/error

    const onLoad = () => {
        console.log("inside load");
        // 执行业务逻辑
    };

    const onError = err => {
        console.log("inside error");
        // 执行业务逻辑
    };

    // 预加载图片处理加载状态
    useEffect(() => {
        const img = new Image();
        img.src = imgSrc;
        img.onload = () => {
            setLoadState('success');
            onLoad();
        };
        img.onerror = (err) => {
            setLoadState('error');
            onError(err);
        };
        return () => {
            img.onload = null;
            img.onerror = null;
        }
    }, [imgSrc]);

    if(loadState === 'loading') return <div>图片加载中</div>
    if(loadState === 'error') return <div>图片加载失败占位</div>

    return (
        <GlassMagnifier
            imageAlt="certificate-preview"
            imageSrc={imgSrc}
            className="image"
            magnifierSize="35%"
        />
    );
});

方案2:自定义轻量圆形放大镜组件(无第三方依赖)

如果不想依赖第三方包,可以自己实现圆形放大镜效果,所有事件完全可控:

组件代码

import { useState, useRef, memo } from "react";
import "./magnifier.css";

export const CustomMagnifierImage = memo(({ 
    src, 
    alt = "preview", 
    width = 200, 
    height = 300, 
    magnifyScale = 2,
    onLoad, 
    onError 
}) => {
  const [showMagnifier, setShowMagnifier] = useState(false);
  const [magnifierPos, setMagnifierPos] = useState({ x: 0, y: 0 });
  const imgRef = useRef(null);
  const magnifierSize = width * 0.35; // 35%的放大镜尺寸,可自行调整

  const handleMouseMove = (e) => {
    const rect = imgRef.current.getBoundingClientRect();
    const x = e.clientX - rect.left;
    const y = e.clientY - rect.top;
    // 限制放大镜不超出图片边界
    const safeX = Math.max(0, Math.min(x, width));
    const safeY = Math.max(0, Math.min(y, height));
    setMagnifierPos({ x: safeX, y: safeY });
  };

  return (
    <div className="magnifier-wrapper" style={{ width, height }}>
      {/* 原图直接绑定onLoad/onError事件 */}
      <img
        ref={imgRef}
        src={src}
        alt={alt}
        onLoad={onLoad}
        onError={onError}
        onMouseEnter={() => setShowMagnifier(true)}
        onMouseLeave={() => setShowMagnifier(false)}
        onMouseMove={handleMouseMove}
        className="original-image"
        style={{ width, height }}
      />
      {/* 圆形放大镜 */}
      {showMagnifier && (
        <div
          className="magnifier-glass"
          style={{
            width: magnifierSize,
            height: magnifierSize,
            left: `${magnifierPos.x}px`,
            top: `${magnifierPos.y}px`,
            backgroundImage: `url(${src})`,
            backgroundSize: `${width * magnifyScale}px ${height * magnifyScale}px`,
            backgroundPosition: `-${magnifierPos.x * magnifyScale - magnifierSize/2}px -${magnifierPos.y * magnifyScale - magnifierSize/2}px`,
          }}
        />
      )}
    </div>
  );
});

对应样式magnifier.css

.magnifier-wrapper {
  position: relative;
}
.original-image {
  display: block;
  object-fit: contain;
}
.magnifier-glass {
  position: absolute;
  border: 2px solid #fff;
  border-radius: 50%;
  cursor: none;
  transform: translate(-50%, -50%);
  pointer-events: none;
  box-shadow: 0 0 10px rgba(0,0,0,0.3);
}

内容的提问来源于stack exchange,提问作者nikita kumari

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 01:39:02