React Three Fiber加载FBX模型阻塞页面动画的解决方法
问题原因
默认useFBX的模型下载、解析逻辑全跑在浏览器主线程,只要FBX模型面数高、材质贴图数据多,解析阶段会长时间占满主线程,直接阻塞CSS动画、DOM渲染的执行,文本动画自然会卡顿停滞。
解决方法
按优先级从高到低尝试即可:
- 优先把FBX转成glTF/GLB格式
FBX是为专业3D软件设计的格式,结构冗余,Web端解析效率极低。glTF是专门针对Web3D优化的格式,解析速度是FBX的3-10倍,配合Draco压缩后体积还能缩小60%以上,解析时对主线程的占用会大幅降低。转完格式后用useGLTF替换useFBX加载即可,API用法完全一致。 - 延后3D模型加载时机,先保证DOM动画首帧渲染
不要页面一加载就同时启动文本动画和3D模型加载,等文本动画完成首帧绘制、主线程空闲后再挂载模型组件,修改代码如下:import { useEffect, useState } from 'react' import { Canvas } from '@react-three/fiber' import { PerspectiveCamera, OrbitControls, useFBX } from '@react-three/drei' const Scene = () => { const fbx = useFBX("FLEX2_matselections.fbx"); return <primitive object={fbx} scale={0.03} />; }; export default function MainPage() { const [canLoadModel, setCanLoadModel] = useState(false) // 等浏览器主线程空闲时再启动模型加载,不抢占文本动画资源 useEffect(() => { const idleTask = window.requestIdleCallback ? window.requestIdleCallback(() => setCanLoadModel(true)) : setTimeout(() => setCanLoadModel(true), 300) return () => { window.requestIdleCallback ? window.cancelIdleCallback(idleTask) : clearTimeout(idleTask) } }, []) return ( <div className='background-main-page'> <h1 className='mainpage-hacking-text'> This is the limited edition of NFT sneakers collectible. <br /> There are only 10.000 pieces in the entire world. <br /> The sneakers are in both, physical and digital form </h1> <Canvas className='canvas'> <PerspectiveCamera makeDefault position={[17, 2, 3]} /> <OrbitControls autoRotate enableZoom={false} minPolarAngle={Math.PI / 2.8} maxPolarAngle={Math.PI / 2.8} /> <ambientLight intensity={0.5} /> <directionalLight position={[-2, 5, 2]} /> <Suspense fallback={null}> {canLoadModel && <Scene />} </Suspense> </Canvas> </div> ); } - 开启React并发模式
不要用旧版ReactDOM.render挂载应用,改用React 18的createRootAPI挂载根节点,开启并发渲染后,React会自动调整任务优先级,DOM动画、用户交互的优先级会高于3D场景渲染,大幅减少卡顿感。 - 从资源侧压缩模型体积
用Blender等3D软件打开你的FBX文件,删除冗余顶点、不可见面、多余材质球,将贴图分辨率压缩到2048px以下,模型总面数控制在10万面以内,从根源上缩短模型解析的耗时。
额外提醒:你原代码里h1标签最后一段文本拼写有误,
digital fo应该是digital form。
内容的提问来源于stack exchange,提问作者Razmi
相关产品推荐
相关产品推荐

