Expo托管项目中Canvas嵌套View无法渲染OBJ模型的求助
React Native中@react-three/fiber的Canvas在View内无法显示3D模型的问题
我正在跟着一篇3D动画教程做React Native项目,目前应用运行正常,但把3D模型组件放在View里就出问题——不包裹View时一切正常,包裹后就无法显示。
ShoeModel组件代码
import { Canvas, useLoader } from '@react-three/fiber/native'; import { Suspense, useLayoutEffect, useRef } from 'react'; import { OBJLoader } from 'three/examples/jsm/loaders/OBJLoader'; import { MTLLoader } from 'three/examples/jsm/loaders/MTLLoader'; import { TextureLoader } from 'expo-three'; function Shoe(props) { const [base, normal, rough] = useAsset(() => [ require('../../../assets/Airmax/textures/BaseColor.jpg'), require('../../../assets/Airmax/textures/Normal.jpg'), require('../../../assets/Airmax/textures/Roughness.png'), ]); const material = useAsset(() => MTLLoader.loadAsync(require('../../../assets/Airmax/shoe.mtl'))); const obj = useLoader( OBJLoader, require('../../../assets/Airmax/shoe.obj'), (loader) => { material.preload(); loader.setMaterials(material); } ); const mesh = useRef(); useLayoutEffect(() => { obj.traverse((child) => { if (child instanceof THREE.Mesh) { child.material.map = base; child.material.normalMap = normal; child.material.roughnessMap = rough; } }); }, [obj]); return ( <mesh ref={mesh} rotation={[0.7, 0, 0]}> <primitive object={obj} scale={10} /> </mesh> ); } export default function ShoeModel() { return ( <Canvas> <ambientLight /> <pointLight position={[10, 10, 10]} /> <Suspense fallback={null}> <Shoe /> </Suspense> </Canvas> ); }
调用组件的代码
import ShoeModel from './components/039/ShoePreview'; export default class ShoeScreen extends React.Component{ render () { return ( <View> <ShoeModel /> </View> ); } }
问题分析与解决方案
你的判断正确,@react-three/fiber的Native版本Canvas在React Native的View容器中需要明确的尺寸约束,默认情况下父容器无尺寸限制时,Canvas无法正确渲染。以下是几种可行的解决办法:
给包裹的View设置明确宽高
通过StyleSheet给View添加固定或百分比尺寸:import ShoeModel from './components/039/ShoePreview'; import { View, StyleSheet } from 'react-native'; export default class ShoeScreen extends React.Component{ render () { return ( <View style={styles.canvasContainer}> <ShoeModel /> </View> ); } } const styles = StyleSheet.create({ canvasContainer: { width: '100%', height: 400, // 根据需求调整高度 backgroundColor: '#f5f5f5', // 可选,便于观察容器范围 } });直接给Canvas组件设置尺寸
在ShoeModel的Canvas组件上添加style属性指定尺寸:export default function ShoeModel() { return ( <Canvas style={{ width: '100%', height: 400 }}> <ambientLight /> <pointLight position={[10, 10, 10]} /> <Suspense fallback={null}> <Shoe /> </Suspense> </Canvas> ); }使用Flex布局让View占满可用空间
如果希望Canvas占满父容器的可用空间,给View设置flex:1:<View style={{ flex: 1 }}> <ShoeModel /> </View>
优先尝试上述尺寸约束方案,因为你提到不包裹View时功能正常,说明异步加载逻辑没有问题,核心问题是容器尺寸未明确导致Canvas无法渲染。
内容的提问来源于stack exchange,提问作者Raja Uzair Zia
相关产品推荐
相关产品推荐

