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

如何在React网站中集成跟随鼠标光标移动的MetaMask Logo?

如何在React组件中集成鼠标跟随的SVG效果

我明白你作为React新手遇到的困惑——Codepen里的代码能正常运行,但放到自己的React项目里就报错,这是因为Codepen的原生JS写法和React的组件化、状态驱动思路不太一样。下面我会一步步教你把这个效果集成到你的InfoSection组件里:

核心思路

React里我们不会直接像原生JS那样操作DOM元素,而是通过**状态(state)**来控制元素的位置,结合事件监听和样式属性(比如transform)实现跟随效果,同时加入缓动让动画更自然(和MetaMask官网的效果一致)。

步骤1:准备SVG资源

首先把MetaMask的SVG准备好,你可以:

  • 把SVG代码直接转成React组件(推荐,方便后续控制)
  • 或者把SVG保存为文件,通过import引入

假设你已经有了SVG文件(比如metamask-logo.svg),先导入到组件里:

import MetaMaskLogo from './metamask-logo.svg';

步骤2:修改你的InfoSection组件

我们需要添加状态存储鼠标位置,监听鼠标移动事件,然后把位置传递给SVG组件:

import React, { useState, useEffect, useRef } from 'react'
import { InfoContainer, InfoWrapper, InfoRow, Column1, Column2, TextWrapper, Heading, Subtitle, ImgWrap } from './experienceElements';
import MetaMaskLogo from './metamask-logo.svg';

// 新建一个styled组件来包裹SVG,处理跟随效果
import styled from 'styled-components';
const FollowSvg = styled.svg`
  position: absolute;
  transition: transform 0.1s ease-out;
  transform: translate(${props => props.x}px, ${props => props.y}px);
  pointer-events: none; // 避免SVG遮挡页面元素的交互
`;

const InfoSection = ({ lightBg, imgStart, lightText, headLine, id, darkText, }) => {
  // 存储当前鼠标位置
  const [mousePos, setMousePos] = useState({ x: 0, y: 0 });
  // 存储上一次的位置,用于缓动计算
  const prevPosRef = useRef({ x: 0, y: 0 });

  useEffect(() => {
    // 监听鼠标移动事件
    const handleMouseMove = (e) => {
      // 计算缓动后的位置(这里用0.2的系数,你可以调整让效果更明显或更柔和)
      const newX = prevPosRef.current.x + (e.clientX - prevPosRef.current.x) * 0.2;
      const newY = prevPosRef.current.y + (e.clientY - prevPosRef.current.y) * 0.2;
      setMousePos({ x: newX, y: newY });
      prevPosRef.current = { x: newX, y: newY };
    };

    window.addEventListener('mousemove', handleMouseMove);
    // 组件卸载时移除监听,避免内存泄漏
    return () => window.removeEventListener('mousemove', handleMouseMove);
  }, []);

  return (
    <InfoContainer lightBg={lightBg} id={id}>
      <InfoWrapper>
        <InfoRow imgStart={imgStart}>
          <Column1>
            <TextWrapper>
              <Heading lightText={lightText}>{headLine}</Heading>
              <Subtitle darkText={darkText}>1. Open a Metamask wallet - it's free</Subtitle>
              <Subtitle darkText={darkText}>2. Upload a picture</Subtitle>
              <Subtitle darkText={darkText}>3. Publish on OpenSea</Subtitle>
            </TextWrapper>
          </Column1>
          <Column2>
            <ImgWrap style={{ position: 'relative', minHeight: '300px' }}>
              {/* 这里放跟随的SVG */}
              <FollowSvg 
                src={MetaMaskLogo} 
                alt="MetaMask Logo" 
                x={mousePos.x - 50} // 减去SVG宽度的一半,让光标在SVG中心
                y={mousePos.y - 50} // 减去SVG高度的一半
                width="100" // 设置合适的大小
                height="100"
              />
            </ImgWrap>
          </Column2>
        </InfoRow>
      </InfoWrapper>
    </InfoContainer>
  )
}
export default InfoSection

步骤3:调整样式细节

  • 给ImgWrap加上position: relative,这样SVG的绝对定位会相对于这个容器,不会乱跑
  • 调整FollowSvg的x和y值,减去SVG宽高的一半,让鼠标光标落在SVG的中心位置,更符合MetaMask的效果
  • 可以修改缓动系数(0.2),数值越大,跟随速度越快;越小则越柔和
  • 添加pointer-events: none,避免SVG遮挡页面其他元素的交互

为什么Codepen的代码直接粘不行?

Codepen里的代码通常是原生JS直接操作DOM(比如用document.getElementById获取元素,然后修改style.transform),但React的组件是状态驱动的:

  1. 组件挂载前DOM元素还不存在,直接操作会报错
  2. React的虚拟DOM会覆盖你手动修改的DOM样式,导致效果失效
  3. 不符合React的数据流规范,后续难以维护

用状态+props的方式,完全符合React的设计思路,也能避免这些问题。

内容的提问来源于stack exchange,提问作者alex deralu

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 11:29:07