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

react-three-fiber中react-spring动画仅点击生效不响应hover问题

问题根源

你遇到的问题来自两个核心冲突:

  1. 旋转属性的控制权冲突:你同时通过两个逻辑修改立方体的rotation属性:
    • useFrame钩子每一帧直接修改boxRef.current.rotation的数值
    • react-spring通过animated.mesh的rotation绑定属性控制同一个值
      二者的修改会互相覆盖,只有组件触发重渲染时,spring的赋值才会暂时生效,这就是为什么只有点击修改active状态触发重渲染时,你才能看到复位效果。
  2. 复位动画触发后没有停止自动旋转:就算hover成功触发了spring复位,useFrame的逻辑还是会在每一帧继续修改旋转角度,你看不到复位的完整动画。

修复方案

按以下步骤修改代码即可解决问题:

  1. 新增状态控制自动旋转的启停
  2. 所有旋转逻辑统一交给react-spring控制,避免直接操作ref属性覆盖动画值
  3. 调整useSpring的调用逻辑,确保hover时正确触发复位

修复后的代码示例:

export const Box = () => {
  const [active, setActive] = useState(false);
  // 新增状态控制自动旋转是否开启
  const [isRotating, setIsRotating] = useState(true);

  const starterRotation = [0, 1, 1];

  // 所有旋转都交给spring控制,不再直接修改ref
  const [rot, setRot] = useSpring(() => ({
    rotation: starterRotation
  }));
  const springs = useSpring({ scale: active ? 1.5 : 1, config: config.wobbly });

  // useFrame直接更新spring的旋转值,不再操作ref
  useFrame(() => {
    if (isRotating) {
      setRot.start(prev => ({
        rotation: [prev.rotation[0] + 0.01, prev.rotation[1] - 0.01, prev.rotation[2]]
      }))
    }
  });

  return (
    <animated.mesh
      rotation={rot.rotation}
      scale={springs.scale}
      onClick={() => setActive(!active)}
      // hover时停止自动旋转,触发复位到初始角度
      onPointerOver={() => {
        setIsRotating(false);
        setRot.start({ rotation: starterRotation });
      }}
      // 鼠标离开后重新开启自动旋转
      onPointerOut={() => setIsRotating(true)}
    >
      <boxGeometry args={[2, 1, 2]} />
      <meshStandardMaterial color="royalblue" />
    </animated.mesh>
  );
};

补充说明

如果你不想把自动旋转也交给spring控制,也可以在hover触发复位的同时,临时把boxRef的控制权交还给spring,等复位动画完成后再重新开启useFrame的修改逻辑,不过统一用spring控制动画属性是更符合react-spring设计规范的写法,后续维护也更简单。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 09:54:01