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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 23:44:58