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

解决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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 06:13:15