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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 05:06:07