React Three Fiber使用@react-spring/three实现相机补间动画方案咨询
根因说明
你遇到的失效问题是@react-spring/three v9版本重构后API发生了Breaking Change,旧版本中用于获取内部值的payload、_value等私有属性均已被移除,官方不再允许直接访问内部结构,必须使用暴露的公共API取值。
以下是两种可落地的最优实现方案:
方案1:声明式动画写法(官方推荐)
这种写法完全符合react-spring的设计理念,不需要手动在useFrame中更新属性,所有动画更新由框架自动处理,性能最优:
import { useSpring, animated } from "@react-spring/three"; import { useThree } from "@react-three/fiber"; // 封装Three.js原生相机为动画响应组件 const AnimatedCamera = animated(useThree().camera); export default function CameraTween(props) { const [spring, api] = useSpring(() => ({ position: [0, 0, 5], // 替换为你的初始位置 lookAt: [0, 0, 0], // 替换为你的初始看向点 config: { duration: 1000, easing: easings.easeCubicInOut }, onRest: () => { if (props.enableOrbit) { props.parentStateModifier({ enableOrbit: true }); } } })) // 监听props变化触发动画 useEffect(() => { api.start({ position: props.position, lookAt: props.lookAt, offset: props.offset }) }, [props.position, props.lookAt, props.offset, api]) return <AnimatedCamera position={spring.position} lookAt={spring.lookAt} /> }
方案2:手动更新写法(兼容旧逻辑)
如果你不想调整现有逻辑结构,可以使用官方暴露的get()方法直接获取spring当前值,不管是否处于动画状态都能正常返回:
import { useSpring } from "@react-spring/three"; import { useFrame, useThree } from "@react-three/fiber"; export default function CameraTween(props) { const { camera } = useThree(); const [spring, api] = useSpring(() => ({ position: [0, 0, 5], lookAt: [0, 0, 0], offset: 0, config: { duration: 1000, easing: easings.easeCubicInOut }, onRest: () => { if (props.enableOrbit) { props.parentStateModifier({ enableOrbit: true }); } } })) useEffect(() => { api.start({ position: props.position, lookAt: props.lookAt, offset: props.offset }) }, [props.position, props.lookAt, props.offset, api]) useFrame(() => { // 调用get()获取当前最新的动画值 const pos = spring.position.get(); const look = spring.lookAt.get(); camera.position.set(pos[0], pos[1], pos[2]); camera.lookAt(look[0], look[1], look[2]); camera.updateProjectionMatrix(); }); }
注意事项
- 不要访问任何以下划线开头的私有属性、以及未出现在官方文档中的内部结构(如之前的
payload),这类属性属于框架内部实现,随时会在版本迭代中被移除。 - 如果项目中使用了
OrbitControls,动画触发前记得将controls的enabled属性设为false,避免用户操作和动画产生冲突。
内容的提问来源于stack exchange,提问作者tinytree
相关产品推荐
相关产品推荐

