使用Forge Viewer API的loadDocumentNode传入数组仅加载单个元素的问题
问题分析与解决方案
一、加载多个dbIds仅显示单个的原因及修复
核心问题是异步加载逻辑处理不当:
- 旧版本Forge Viewer的
viewer.loadDocumentNode并不返回Promise,直接用await无法等待模型加载完成,后续代码提前执行会干扰加载流程,导致部分元素未被正确加载。 - 需额外确认传入的
dbIds均为数值类型,Viewer对dbIds类型校验严格,字符串类型的id会被直接忽略。
二、fitToView无法适配视图的原因及修复
fitToView必须在模型几何完全加载完成后调用,否则Viewer无法识别未加载的元素,自然无法调整视图。直接在loadDocumentNode后调用时,模型可能还在解析阶段,元素并未真正渲染到场景中。
三、修改后的完整代码
async function loadAndInitializeForgeViewer(urn, accessToken, dbIds) { if (typeof Autodesk === 'undefined') { console.log("Autodesk namespace not found, loading Forge Viewer scripts..."); try { // Load Forge Viewer CSS await new Promise((resolve, reject) => { var link = document.createElement('link'); link.rel = 'stylesheet'; link.href = 'https://developer.api.autodesk.com/modelderivative/v2/viewers/style.min.css'; link.onload = resolve; link.onerror = reject; document.head.appendChild(link); }); // Load Forge Viewer JS await new Promise((resolve, reject) => { var script = document.createElement('script'); script.src = 'https://developer.api.autodesk.com/modelderivative/v2/viewers/viewer3D.min.js'; script.onload = resolve; script.onerror = reject; document.head.appendChild(script); }); console.log("Forge Viewer scripts loaded successfully."); } catch (error) { console.error("Error loading Forge Viewer scripts:", error); return; } } else { console.log("Forge Viewer scripts already loaded."); } await initializeForgeViewer(urn, accessToken, dbIds); } let globalViewer = null; async function initializeForgeViewer(encodedUrn, accessToken, dbIds) { let options = { env: 'AutodeskProduction', getAccessToken: (callback) => { callback(accessToken, 3600); // Access token expires in 3600 seconds (1 hour) } }; Autodesk.Viewing.Initializer(options, () => { let viewerDiv = document.getElementById('forgeViewerContainer'); globalViewer = new Autodesk.Viewing.GuiViewer3D(viewerDiv); const startedCode = globalViewer.start(); if (startedCode > 0) { console.error('Failed to create a Viewer: WebGL not supported.'); return; } let documentId = 'urn:' + encodedUrn; Autodesk.Viewing.Document.load(documentId, (doc) => { let viewables = doc.getRoot().getDefaultGeometry(); if (!viewables) { console.error("No viewable geometry found in the document."); return; } // 确保dbIds是数值类型数组,过滤无效值 const validDbIds = dbIds.map(id => Number(id)).filter(id => !isNaN(id)); console.log("Loading model with specified element IDs:", validDbIds); const loadOptions = { ids: validDbIds }; // 使用回调处理加载完成,适配旧版本Viewer的异步逻辑 globalViewer.loadDocumentNode(doc, viewables, loadOptions, (model) => { console.log("Model loaded with specified element IDs only."); // 监听几何加载完成事件,确保所有元素渲染完成后再执行视图适配 const onGeometryLoaded = () => { globalViewer.removeEventListener(Autodesk.Viewing.GEOMETRY_LOADED_EVENT, onGeometryLoaded); if (validDbIds.length > 0) { globalViewer.fitToView(validDbIds); console.log("Fitting view to the specified elements."); } }; globalViewer.addEventListener(Autodesk.Viewing.GEOMETRY_LOADED_EVENT, onGeometryLoaded); }, (error) => { console.error("Error loading document node:", error); }); }, (errorCode) => { console.error("Could not load document. Error code:", errorCode); }); }); }
关键修改点
- 修正异步加载逻辑:改用
loadDocumentNode的回调函数处理加载完成,避免旧版本Viewer不支持Promise导致的流程错乱。 - 校验并转换dbIds类型:将所有id转为数值类型并过滤无效值,确保Viewer能正确识别目标元素。
- 延迟执行视图适配:监听
GEOMETRY_LOADED_EVENT事件,等所有几何数据加载完成后再调用fitToView,保证元素已存在于场景中。
内容的提问来源于stack exchange,提问作者Mark McKeon
相关产品推荐
相关产品推荐

