界面组件
<div className='file-btn-container'>
<input className='file-btn' type='file' />
</div>
组件事件
import { IFCLoader } from 'web-ifc-three/dist/IFCLoader';
import { IFCOPENINGELEMENT, IFCSPACE } from 'web-ifc';
import { acceleratedRaycast, computeBoundsTree, disposeBoundsTree } from 'three-mesh-bvh';
export default function DrawPanel() {
const { projectId } = useParams();
const [loading, setLoading] = useState<boolean>(false);
const [loadingTip, setLoadingTip] = useState<string>('');
const [sceneUpdate, setSceneUpdate] = useState<string>(''); // 场景更新的信号
const systemContext = useContext<SystemStatus>(SystemContext);
const drawRef = useRef(null);
const [ifcModels, setIfcModels] = useState<any[]>([]);
const ifcLoader = new IFCLoader();
useEffect(() => {
setupIfcLoader();
setupFileOpener();
}, [])
const setupThreeMeshBVH = () => {
ifcLoader.ifcManager.setupThreeMeshBVH(
computeBoundsTree,
disposeBoundsTree,
acceleratedRaycast
);
}
const setupIfcLoader = async () => {
await ifcLoader.ifcManager.parser.setupOptionalCategories({
[IFCSPACE]: false,
[IFCOPENINGELEMENT]: false
});
// await this.ifcLoader.ifcManager.useWebWorkers(true, 'IFCWorker.js');
setupThreeMeshBVH();
}
const setupFileOpener = () => {
const input = document.querySelector('input[type="file"]');
if (!input) return;
input.addEventListener(
'change',
async (changed) => {
await loadIFC(changed);
},
false
);
}
const loadIFC = async (changed) => {
const start = window.performance.now()
const ifcURL = URL.createObjectURL(changed.target.files[0]);
ifcLoader.ifcManager.setOnProgress((event) => console.log(event));
const firstModel = Boolean(ifcModels.length === 0);
await ifcLoader.ifcManager.applyWebIfcConfig({
COORDINATE_TO_ORIGIN: firstModel
});
const ifcModel: any = await ifcLoader.loadAsync(ifcURL);
if (firstModel) {
const matrixArr: any = ifcLoader.ifcManager.ifcAPI.GetCoordinationMatrix(ifcModel.modelID);
const matrix = new Matrix4().fromArray(matrixArr);
ifcLoader.ifcManager.setupCoordinationMatrix(matrix);
}
ifcModels.push(ifcModel);
setIfcModels(ifcModels);
graphicStore.extraContext.sceneContext.scene.add(ifcModel);
const stop = window.performance.now()
console.log(`Time Taken to load = ${(stop - start) / 1000} seconds`);
}
运行报错
上段代码中主要通过下面这行代码加载ifc文件:
const ifcModel: any = await ifcLoader.loadAsync(ifcURL);
其中,ifcLoader来自web-ifc-three包,但直接npm install的包无法使用,运行报错“wasm streaming compile failed: LinkError: WebAssembly.instantiate(): Import #49 "a" "X": function import requires a callable”。
解决办法
1 从web-ifc下载源码,按照readme文件说明一步一步build项目,最后将整体dist文件夹替换react项目node_modules\web-ifc文件夹;
2 从web-ifc-three下载源码,打开web-ifc-three文件夹,运行npm run build,最后将包含有dist文件夹的整个web-ifc-three文件夹替换react项目node_modules\web-ifc-three文件夹;
3 react项目npm run build,build成功之后,将第1步中dist文件夹中的web-ifc.wasm文件复制到build目录下;
4 配置nginx的config文件,添加以下内容,重启动nginx:
server {
listen 3000;
server_name localhost;
location / {
root "replace with your react project address"/build;
try_files $uri /index.html;
add_header Cache-Control no-store;
}
location ~* \.(wasm)$ {
root "replace with your react project address"/build;
types {
application/wasm wasm;
}
add_header Cache-Control "public, max-age=31536000, immutable";
}
}
5 打开对应端口,即可正常使用;