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

APS Viewer v7工具栏按钮随窗口变化消失及缩放/剖面工具失效问题

问题描述

我开发了一个使用APS Viewer v7的Next.js应用,遇到以下问题:

  • 窗口处于特定显示尺寸时,工具栏多个按钮消失,放大窗口后又重新出现
  • 尝试移除原有按钮再重新添加后,缩放工具失效,剖面工具的折叠按钮完全丢失
  • 希望为自定义按钮添加扩展功能,但文档未明确说明实现方法

相关代码如下:

newViewer.addEventListener(Autodesk.Viewing.GEOMETRY_LOADED_EVENT, () => {
      newViewer.fitToView();

      const toolbar = newViewer.toolbar;

      // define then list the contents of the navTools group
      const navTools = toolbar.getControl("navTools");
      console.log("navTools: ", navTools);
      let firstToolId = navTools.getControlId(0);
      console.log("1stToolId: ", firstToolId);
      let secondToolId = navTools.getControlId(1);
      console.log("2ndToolId: ", secondToolId);
      let thirdToolId = navTools.getControlId(2);
      console.log("3rdToolId: ", thirdToolId);
      let fourthToolId = navTools.getControlId(3);
      console.log("4thToolId: ", fourthToolId);
      let fifthToolId = navTools.getControlId(4);
      console.log("5thToolId: ", fifthToolId);

      // remove the tools so we can repopulate them
      navTools.removeControl("toolbar-orbitTools");
      navTools.removeControl("toolbar-panTool");
      navTools.removeControl("toolbar-zoomTool");
      navTools.removeControl("toolbar-bimWalkTool");
      navTools.removeControl("toolbar-cameraSubmenuTool");

      // define then list the contents of the modelTools group
      const modelTools = toolbar.getControl("modelTools");
      console.log("modelTools: ", modelTools);
      let firstModelToolId = modelTools.getControlId(0);
      console.log("1stToolId: ", firstModelToolId);
      let secondModelToolId = modelTools.getControlId(1);
      console.log("2ndToolId: ", secondModelToolId);
      let thirdModelToolId = modelTools.getControlId(2);
      console.log("3rdToolId: ", thirdModelToolId);
      let fourthModelToolId = modelTools.getControlId(3);
      console.log("4thToolId: ", fourthModelToolId);
      let fifthModelToolId = modelTools.getControlId(4);
      console.log("5thToolId: ", fifthModelToolId);

      //remove the tools so we can repopulate them
      modelTools.removeControl("toolbar-explodeTool");
      // modelTools.removeControl("toolbar-sectionTool");
      let sectionTool = modelTools.getControl("toolbar-sectionTool");
      console.log("sectionTool: ", sectionTool);

      let orbitButton = new Autodesk.Viewing.UI.Button("orbitToolButton");
      orbitButton.onClick = function () {
        newViewer.setActiveNavigationTool("orbit");
      };
      orbitButton.setToolTip("Orbit");
      orbitButton.setIcon("adsk-icon-orbit-constrained");

      let controlGroup = toolbar.getControl("navTools"); // You can use an existing group like navTools
      controlGroup.addControl(orbitButton);

      let panButton = new Autodesk.Viewing.UI.Button("panToolButton");
      panButton.onClick = function () {
        newViewer.setActiveNavigationTool("pan");
      };
      panButton.setToolTip("Pan");
      panButton.setIcon("adsk-icon-pan");
      controlGroup.addControl(panButton);

      // zoom dosent work
      let zoomButton = new Autodesk.Viewing.UI.Button("zoomToolButton");
      zoomButton.onClick = function () {
        newViewer.setActiveNavigationTool("zoom");
      };
      zoomButton.setToolTip("Zoom");
      zoomButton.setIcon("adsk-icon-zoom");
      controlGroup.addControl(zoomButton);

      let fitToViewButton = new Autodesk.Viewing.UI.Button(
        "fitToViewToolButton"
      );
      fitToViewButton.onClick = function () {
        newViewer.fitToView();
      };
      fitToViewButton.setToolTip("fitToView");
      fitToViewButton.setIcon("adsk-icon-fit-to-view");
      controlGroup.addControl(fitToViewButton);

      let firstPersonButton = new Autodesk.Viewing.UI.Button(
        "firstPersonToolButton"
      );
      firstPersonButton.onClick = function () {
        newViewer.setActiveNavigationTool("bimwalk");
      };
      firstPersonButton.setToolTip("First Person");
      firstPersonButton.setIcon("adsk-icon-first-person");
      controlGroup.addControl(firstPersonButton);
      //model tool group
      let modelGroup = toolbar.getControl("modelTools");

      // dosent work
      let sectionAnalysisButton = new Autodesk.Viewing.UI.Button(
        "sectionAnalysisToolButton"
      );
      sectionAnalysisButton.onClick = function () {
        newViewer.setActiveNavigationTool("section");
      };
      sectionAnalysisButton.setToolTip("Section Analysis");
      sectionAnalysisButton.setIcon("adsk-icon-section-analysis");
      modelGroup.addControl(sectionAnalysisButton);
    });

问题分析与解决

1. 窗口尺寸变化导致按钮消失的根源

APS Viewer原生工具栏自带响应式布局逻辑,当窗口宽度不足时,会自动将部分按钮折叠到右侧的溢出下拉菜单中。你手动移除再重新添加按钮的操作,破坏了原生的响应式机制,反而引发更多问题。正确做法是保留原生工具栏控件,不要手动替换。

2. 缩放工具失效的原因

原生缩放工具包含普通缩放和框选缩放两种模式,原生按钮会自动处理模式切换逻辑。而你自定义的缩放按钮仅调用newViewer.setActiveNavigationTool("zoom"),只激活了基础缩放模式,缺失了模式切换功能。

如果必须自定义缩放按钮,需补充模式切换逻辑:

let zoomButton = new Autodesk.Viewing.UI.Button("zoomToolButton");
zoomButton.onClick = function () {
  const currentTool = newViewer.getActiveNavigationTool();
  if (currentTool === "zoom") {
    newViewer.setActiveNavigationTool("boxzoom"); // 切换框选缩放
  } else if (currentTool === "boxzoom") {
    newViewer.setActiveNavigationTool("zoom"); // 切回普通缩放
  } else {
    newViewer.setActiveNavigationTool("zoom");
  }
};
zoomButton.setToolTip("Zoom (点击切换框选模式)");
zoomButton.setIcon("adsk-icon-zoom");

3. 剖面工具折叠按钮丢失的问题

原生剖面工具是一个带子菜单的ControlGroup控件,包含剖面创建、编辑等子按钮。你直接替换成普通按钮后,丢失了原有的折叠/展开逻辑。正确做法是保留原生的toolbar-sectionTool控件,如需修改剖面工具行为,可通过监听Autodesk.Viewing.SECTION_CHANGED_EVENT事件扩展功能,而非替换整个控件。

4. 自定义按钮添加扩展功能的实现

APS Viewer官方推荐用Extension机制封装自定义功能,步骤如下:

步骤1:创建扩展类

class CustomExtension extends Autodesk.Viewing.Extension {
  constructor(viewer, options) {
    super(viewer, options);
    this.button = null;
  }

  load() {
    // 创建自定义按钮
    this.button = new Autodesk.Viewing.UI.Button("custom-extension-btn");
    this.button.setIcon("adsk-icon-custom");
    this.button.setToolTip("我的自定义功能");
    this.button.onClick = () => {
      // 这里编写扩展逻辑
      alert("自定义功能触发!");
      // 示例:隔离指定ID的模型元素
      this.viewer.isolateById(123);
    };

    // 添加按钮到工具栏自定义分组
    const toolbar = this.viewer.toolbar;
    let customGroup = toolbar.getControl("custom-tool-group");
    if (!customGroup) {
      customGroup = new Autodesk.Viewing.UI.ControlGroup("custom-tool-group");
      toolbar.addControl(customGroup);
    }
    customGroup.addControl(this.button);
    return true;
  }

  unload() {
    // 卸载扩展时清理按钮
    const toolbar = this.viewer.toolbar;
    const customGroup = toolbar.getControl("custom-tool-group");
    if (customGroup) {
      customGroup.removeControl(this.button);
      if (customGroup.getNumberOfControls() === 0) {
        toolbar.removeControl(customGroup);
      }
    }
    this.button = null;
    return true;
  }
}

// 注册扩展
Autodesk.Viewing.theExtensionManager.registerExtension('CustomExtension', CustomExtension);

步骤2:加载扩展

在Viewer初始化完成后调用:

viewer.loadExtension('CustomExtension');

总结优化方案

  • 放弃手动替换原生工具栏按钮的操作,保留Viewer原生响应式布局,解决窗口尺寸变化导致按钮消失的问题
  • 如需修改原生工具行为,通过监听事件或扩展原有工具实现,而非完全替换
  • 使用官方Extension机制封装自定义按钮功能,便于功能管理和复用

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 02:00:56