React Three Fiber中GLTFLoader加载的3D模型过小问题
解决React Three Fiber中3D模型过小且自动适配视图的问题
针对你遇到的模型显示极小的问题,完全可以通过自动计算模型包围盒来实现居中适配,无需手动调整缩放和相机位置。以下是修改后的代码和关键逻辑说明:
核心解决方案:基于包围盒自动居中与缩放
在模型加载完成后,利用Three.js的Box3计算模型的整体包围盒,然后:
- 将模型平移到场景原点实现居中
- 根据包围盒尺寸计算合适的缩放比例,让模型刚好适配相机视野
修改后的完整代码
import React, { Suspense, useRef, useEffect } from "react"; import { Canvas, useFrame, useLoader, useThree } from "@react-three/fiber"; import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader"; import { OrbitControls, Environment, Html } from "@react-three/drei"; import * as THREE from "three"; function Model() { const gltf = useLoader(GLTFLoader, "/traveler.glb"); const modelRef = useRef(); const mixer = useRef(); const { camera } = useThree(); const center = new THREE.Vector3(); const size = new THREE.Vector3(); useEffect(() => { if (!gltf?.scene) return; // 1. 计算模型整体包围盒 const box = new THREE.Box3().setFromObject(gltf.scene); // 获取包围盒的中心坐标与尺寸 box.getCenter(center); box.getSize(size); // 2. 计算适配相机视野的缩放比例 const maxDim = Math.max(size.x, size.y, size.z); // 5是基于相机z轴位置(4)的适配值,可根据需求微调 const scale = 5 / maxDim; // 3. 应用居中与缩放设置 modelRef.current.position.set(-center.x, -center.y, -center.z); modelRef.current.scale.setScalar(scale); // 初始化动画播放器 if (gltf.animations.length > 0) { mixer.current = new THREE.AnimationMixer(gltf.scene); gltf.animations.forEach(clip => { const action = mixer.current.clipAction(clip); action.play(); }); } }, [gltf]); useFrame((state, delta) => { if (mixer.current) { mixer.current.update(delta); } }); return ( <primitive ref={modelRef} object={gltf.scene} rotation={[0, Math.PI / 4, 0]} /> ); } function Loader() { return ( <Html center> <div style={{ color: "white", display: "flex", flexDirection: "column", alignItems: "center" }}> <div className="loader"></div> <p>Loading 3D model...</p> </div> </Html> ); } const HeroModel3D = () => { return ( <div className="hero-model-3d"> <Canvas camera={{ position: [0, 0, 4], fov: 45 }} style={{ background: "grey" }} > <ambientLight intensity={0.7} /> <spotLight position={[10, 10, 10]} angle={0.15} penumbra={1} intensity={1.2} castShadow /> <directionalLight position={[-5, 5, -5]} intensity={0.5} /> <Suspense fallback={<Loader />}> <Model /> <Environment preset="city" /> <OrbitControls enableZoom={false} enablePan={false} minPolarAngle={Math.PI / 3} maxPolarAngle={Math.PI / 2} autoRotate={false} rotateSpeed={0.5} /> </Suspense> </Canvas> </div> ); }; export default HeroModel3D;
关键逻辑说明
- 包围盒计算:
Box3().setFromObject(gltf.scene)会遍历模型所有子网格,计算出覆盖整个模型的最小包围盒,确保包含所有可见元素 - 居中处理:将模型位置设置为包围盒中心的负值,让模型的几何中心与场景原点重合,实现自动居中
- 缩放计算:通过模型最大边长与相机视野的比例(
5 / maxDim),确保模型不会超出相机可见范围,这个数值可以根据你想要的显示大小微调 - 动画兼容:包围盒计算在动画初始化前完成,避免动画帧干扰尺寸计算
内容的提问来源于stack exchange,提问作者Sithil Sandinu
相关产品推荐
相关产品推荐

