react-three-fiber中react-spring动画仅点击生效不响应hover问题
问题根源
你遇到的问题来自两个核心冲突:
- 旋转属性的控制权冲突:你同时通过两个逻辑修改立方体的
rotation属性:useFrame钩子每一帧直接修改boxRef.current.rotation的数值- react-spring通过
animated.mesh的rotation绑定属性控制同一个值
二者的修改会互相覆盖,只有组件触发重渲染时,spring的赋值才会暂时生效,这就是为什么只有点击修改active状态触发重渲染时,你才能看到复位效果。
- 复位动画触发后没有停止自动旋转:就算hover成功触发了spring复位,
useFrame的逻辑还是会在每一帧继续修改旋转角度,你看不到复位的完整动画。
修复方案
按以下步骤修改代码即可解决问题:
- 新增状态控制自动旋转的启停
- 所有旋转逻辑统一交给react-spring控制,避免直接操作ref属性覆盖动画值
- 调整
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
相关产品推荐
相关产品推荐

