解决Forge Viewer中树形选择设备无法缩放及获取选中对象问题
Forge Viewer 树形面板选中设备无自动缩放的解决需求
我们使用Forge Viewer展示BIM模型时,点击树形选择面板中的任意设备,Viewer内的对应设备不会自动缩放。需解决以下两个需求:
- 获取选中的设备对象
- 实现选中设备在Viewer中的自动缩放功能
现有代码如下:
Autodesk.Viewing.Initializer(options, function () { // Get the viewer div const viewerDiv = document.getElementById('forgeViewer'); // Initialize the viewer object const viewer = new Autodesk.Viewing.GuiViewer3D(viewerDiv); viewer.start(); // Ensure event listeners are added only once viewer.addEventListener(Autodesk.Viewing.TOOLBAR_CREATED_EVENT, onToolbarCreated); viewer.addEventListener(Autodesk.Viewing.GEOMETRY_LOADED_EVENT, Loadedevent); // Initialize the AggregatedView const view = new Autodesk.Viewing.AggregatedView(); view.init(viewerDiv, options3d); // Use the same viewer instance const aggregatedViewer = view.viewer; // Set custom profile settings const customProfileSettings = { settings: { reverseMouseZoomDir: true, reverseHorizontalLookDirection: true, selectionMode: 1 // enum value, 0 is default 'First Object' is 1 } }; const customProfile = new Autodesk.Viewing.Profile(customProfileSettings); viewer.setProfile(customProfile); // Optimize viewer settings viewer.setQualityLevel(false, false); // Disable ambient occlusion and antialiasing viewer.setGroundShadow(false); // Disable ground shadow viewer.setGroundReflection(false); // Disable ground reflection viewer.setProgressiveRendering(true); // Enable progressive rendering // Load all manifests const tasks = models.map(md => loadManifest(md.urn, aggregatedViewer)); Promise.all(tasks) .then(docs => Promise.resolve(docs.map(doc => { const bubbles = doc.getRoot().search({ type: 'geometry', role: '3d' }); const bubble = bubbles[0]; if (!bubble) return null; return bubble; }))) .then(bubbles => view.setNodes(bubbles)); }); // loadManifest function function loadManifest(documentId, viewer) { debugger; return new Promise((resolve, reject) => { const onDocumentLoadSuccess = (doc) => { doc.downloadAecModelData(() => resolve(doc)); // New code for handling selection changes viewer.addEventListener(Autodesk.Viewing.AGGREGATE_SELECTION_CHANGED_EVENT, (event) => { if (!event.selections || event.selections.length <= 0 || event.selections.length > 1) return; const selSet = event.selections[0]; const dbIds = selSet.dbIdArray; const model = selSet.model; const dbId = dbIds[0]; model.getProperties(dbId, function (data) { if (FromPage == '') { if (FromSelection == '') { if (Count === 0) { let instanceTree = model.getInstanceTree(); let parentId = instanceTree.getNodeParentId(dbId); var objectid = parentId + 1; if (objectid === PreviousParentId) { Count = 1; selectionchangecount = 0; } else { viewer.select(parentId, model, Autodesk.Viewing.SelectionType.OVERLAYED); // or viewer.setAggregateSelection([ { ids: [parentId ], model, selectionType: Autodesk.Viewing.SelectionType.OVERLAYED } ]) Count = 1; selectionchangecount = 0; } PreviousParentId = parentId; } else { itemobject = dbId; selectionchangecount = selectionchangecount + 1; if (selectionchangecount == fileselectioncount) { Count = 0; selectionchangecount = 0; } } } else { selectionchangecount = selectionchangecount + 1; if (selectionchangecount == filecount) { FromSelection = ''; selectionchangecount = 0; } itemobject = dbId; } } else { FromPage = ''; itemobject = dbId; } }); }); }; Autodesk.Viewing.Document.load(documentId, onDocumentLoadSuccess, reject); }); }
解决方案
1. 获取选中的设备对象
原代码已通过AGGREGATE_SELECTION_CHANGED_EVENT事件拿到选中项的dbId和对应model,可直接通过model.getProperties获取设备完整属性信息。需注意避免重复添加事件监听(原代码每次加载模型都会新增监听,导致多次触发),建议将事件监听移到Viewer初始化完成后统一添加。
2. 实现自动缩放功能
Forge Viewer内置fitToView方法,可将指定对象缩放到视图中心并适配窗口。在选中事件回调中调用该方法即可实现自动缩放。
修改后的核心代码示例
调整事件监听位置,并添加缩放逻辑:
Autodesk.Viewing.Initializer(options, function () { // ... 保留原有初始化代码 ... // 待所有模型加载完成后添加选择事件监听(避免重复绑定) Promise.all(tasks) .then(docs => Promise.resolve(docs.map(doc => { const bubbles = doc.getRoot().search({ type: 'geometry', role: '3d' }); const bubble = bubbles[0]; if (!bubble) return null; return bubble; }))) .then(bubbles => view.setNodes(bubbles)) .then(() => { // 统一添加选择变更事件监听 aggregatedViewer.addEventListener(Autodesk.Viewing.AGGREGATE_SELECTION_CHANGED_EVENT, handleSelectionChange); }); }); // 单独提取选择变更处理函数 function handleSelectionChange(event) { if (!event.selections || event.selections.length === 0) return; const selSet = event.selections[0]; const dbIds = selSet.dbIdArray; const model = selSet.model; if (!model || dbIds.length === 0) return; // 1. 获取选中设备的属性对象 model.getProperties(dbIds[0], (props) => { console.log('选中设备详情:', props); // 可在此处将设备信息存储或展示到页面 }); // 2. 自动缩放到选中设备 aggregatedViewer.fitToView(dbIds, model); } // 修改loadManifest函数,移除重复的事件监听 function loadManifest(documentId, viewer) { return new Promise((resolve, reject) => { const onDocumentLoadSuccess = (doc) => { doc.downloadAecModelData(() => resolve(doc)); // 移除原有的事件监听代码 }; Autodesk.Viewing.Document.load(documentId, onDocumentLoadSuccess, reject); }); }
关键说明
- 事件监听需确保只绑定一次,避免重复触发逻辑
fitToView方法支持传入单个或多个dbId,可适配多选场景- 若需聚焦到父节点(如原代码中的
parentId),可将dbIds替换为[parentId]再调用fitToView
内容的提问来源于stack exchange,提问作者E.M Pradeep
相关产品推荐
相关产品推荐

