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

React-TypeScript中Three.js模型平滑过渡新尺寸问题求助

解决Three.js + React-TypeScript中模型尺寸平滑过渡问题

核心问题是你直接将接收到的尺寸值赋值给模型的scale属性,导致尺寸突变。要实现平滑过渡,需要通过帧动画插值逐步让当前尺寸逼近目标尺寸,而不是直接替换。下面是具体实现方案:

步骤1:维护目标尺寸与当前尺寸状态

在组件中分别存储两个状态:

  • targetScale:WebSocket传来的目标尺寸值
  • currentScale:模型当前的过渡尺寸值(用于渲染)
import { useState, useEffect, useRef } from 'react';
import { useFrame } from '@react-three/fiber';
import { Mesh, BoxGeometry, MeshBasicMaterial } from 'three';

export default function ScalingModel() {
  // 初始尺寸设为1,可按需调整
  const [targetScale, setTargetScale] = useState(1);
  const [currentScale, setCurrentScale] = useState(1);
  const meshRef = useRef<Mesh>(null);

  // WebSocket连接与消息处理
  useEffect(() => {
    const ws = new WebSocket('ws://your-backend-url');
    ws.onmessage = (event) => {
      const newSize = parseFloat(event.data);
      // 仅更新目标尺寸,不直接修改模型scale
      setTargetScale(newSize);
    };
    return () => ws.close();
  }, []);

  // 帧动画中执行平滑插值
  useFrame(() => {
    if (!meshRef.current) return;
    // 线性插值:每帧让当前尺寸向目标尺寸靠近10%
    const lerpFactor = 0.1;
    const newCurrentScale = currentScale + (targetScale - currentScale) * lerpFactor;
    setCurrentScale(newCurrentScale);
    // 将插值后的尺寸应用到模型
    meshRef.current.scale.setScalar(newCurrentScale);
  });

  return (
    <mesh ref={meshRef} rotation-y={Math.sin(Date.now() * 0.001)}>
      <boxGeometry />
      <meshBasicMaterial color="red" />
    </mesh>
  );
}

关键细节说明

  • 插值方式:示例用了线性插值(lerp),也可以用smoothstep实现更自然的缓动效果:
    // 平滑缓动插值,过渡更柔和
    const diff = Math.abs(targetScale - currentScale);
    const t = Math.min(1, diff / 0.1);
    const easedT = t * t * (3 - 2 * t);
    const newCurrentScale = currentScale + (targetScale - currentScale) * easedT;
    
  • 插值系数:lerpFactor控制过渡速度,取值01,值越大过渡越快,越小越慢。结合2秒的消息周期,建议设为`0.05~0.1`,让过渡在12秒内完成。
  • 避免直接修改模型属性:所有尺寸变更都通过帧动画处理,不要在WebSocket回调中直接修改mesh.scale,否则会打断过渡动画。
  • 旋转动画:示例中用rotation-y={Math.sin(Date.now() * 0.001)}实现基础旋转,可替换为自定义的旋转逻辑。

排查常见问题

如果过渡仍不生效,检查:

  • 是否正确使用了useFrame(@react-three/fiber提供的帧循环钩子),若不用r3f,需手动创建requestAnimationFrame循环。
  • currentScale是否在每帧更新时正确赋值给模型。
  • WebSocket传递的数值是否正确解析为数字类型,避免字符串导致计算错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 09:22:12