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

如何用React-map-gl、Deck.gl加载用户上传的IFC/GLTF模型

问题解决:用户上传GLTF/IFC模型在deck.gl中加载失败

一、GLTF模型加载错误解决

错误信息

deck: loading scenegraph of ScenegraphLayer({id: 'scenegraph-layer'}): No valid loader found (0f3e4b8a-f7d4-4cbd-868e-c4c463552bca, MIME type: not provided, first bytes: not available)

问题原因

  1. ScenegraphLayer默认未显式指定GLTF加载器,Blob URL的MIME类型未被正确识别
  2. 初始状态下gltfUrl为undefined,此时创建的ScenegraphLayer会尝试加载空资源触发错误

解决方案

  1. 安装@loaders.gl/gltf依赖,提供GLTF专用加载器
  2. 显式为ScenegraphLayer指定loader为GLTFLoader
  3. 仅当gltfUrl存在时才创建ScenegraphLayer,避免无效加载

修改后的代码

import { useState } from 'react';
import { Map } from 'react-map-gl';
import { ScenegraphLayer } from '@deck.gl/mesh-layers';
import { DeckGL } from 'deck.gl';
import maplibreGl from 'maplibre-gl';
import { GLTFLoader } from '@loaders.gl/gltf';

function App() {
  const [gltfUrl, setGltfUrl] = useState();

  const gltfUpload = (e) => {
    const file = e.target.files[0];
    const url = URL.createObjectURL(file);
    setGltfUrl(url);
  };

  // 仅当gltfUrl存在时创建图层
  const layers = gltfUrl ? [new ScenegraphLayer({
    id: 'scenegraph-layer',
    pickable: true,
    data: [
      {
        name: 'Colma (COLM)',
        address: '365 D Street, Colma CA 94014',
        exits: 4214,
        coordinates: [148.9819, -35.39847],
      },
    ],
    scenegraph: gltfUrl,
    loader: GLTFLoader, // 显式指定GLTF加载器
    getPosition: (d) => d.coordinates,
    getOrientation: (d) => [0, Math.random() * 180, 90],
    sizeScale: 1,
    _lighting: 'pbr',
  })] : [];

  return (
    <>
      <input
        type='file'
        onChange={gltfUpload}
        style={{ zIndex: 10, position: 'fixed' }}
        accept=".gltf,.glb" // 限制文件类型,避免错误上传
      />
      <DeckGL
        initialViewState={{
          longitude: 148.9819,
          latitude: -35.39847,
          zoom: 18,
          pitch: 60,
        }}
        controller={true}
        layers={layers}
      >
        <Map
          mapLib={maplibreGl}
          mapStyle='https://api.maptiler.com/maps/basic/style.json?key=get_your_own_OpIi9ZULNHzrESv6T2vL'
        />
      </DeckGL>
    </>
  );
}

export default App;

二、IFC模型加载错误解决

错误信息

Uncaught (in promise) Error: Cannot convert supplied data type at getArrayBufferOrStringFromData

问题原因

  1. Tile3DLayer + I3SLoader用于加载I3S格式的3D瓦片数据集,无法直接加载web-ifc-three输出的Three.js Object3D对象
  2. IFC模型加载后需要转换为deck.gl可识别的场景图格式,而非直接传入Tile3DLayer

解决方案

  1. 使用web-ifc-three加载IFC得到Three.js Object3D
  2. 将加载后的Object3D传入ScenegraphLayer作为scenegraph(deck.gl支持直接传入Three.js对象)
  3. 调整图层配置,适配IFC模型的位置与缩放

修改后的代码

import { useState, useRef } from 'react';
import maplibregl from 'maplibre-gl';
import DeckGL from '@deck.gl/react';
import { Map } from 'react-map-gl';
import { ScenegraphLayer } from '@deck.gl/mesh-layers';
import { IFCLoader } from 'web-ifc-three';

function App() {
  const [ifcModel, setIfcModel] = useState();
  const ifcLoaderRef = useRef(new IFCLoader());

  const ifcUpload = async (e) => {
    const file = e.target.files[0];
    const url = URL.createObjectURL(file);
    try {
      const model = await ifcLoaderRef.current.loadAsync(url);
      // 可选:调整模型缩放,默认IFC模型可能尺寸过大
      model.scale.set(0.01, 0.01, 0.01);
      setIfcModel(model);
    } catch (err) {
      console.error('IFC加载失败:', err);
    }
  };

  // 仅当ifcModel存在时创建图层
  const layers = ifcModel ? [new ScenegraphLayer({
    id: 'ifc-scenegraph-layer',
    pickable: true,
    data: [
      {
        coordinates: [148.9819, -35.39847],
      },
    ],
    scenegraph: ifcModel, // 直接传入Three.js Object3D
    getPosition: (d) => d.coordinates,
    getOrientation: () => [0, 0, 0],
    sizeScale: 1,
    _lighting: 'pbr',
  })] : [];

  return (
    <>
      <input
        type='file'
        onChange={ifcUpload}
        style={{ zIndex: 10, position: 'fixed' }}
        accept=".ifc" // 限制文件类型
      />
      <DeckGL
        initialViewState={{
          longitude: 148.9819,
          latitude: -35.39847,
          zoom: 18,
          pitch: 60,
        }}
        controller={true}
        layers={layers}
      >
        <Map
          mapLib={maplibregl}
          mapStyle='https://api.maptiler.com/maps/basic/style.json?key=get_your_own_OpIi9ZULNHzrESv6T2vL'
        />
      </DeckGL>
    </>
  );
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 14:53:17