资讯专栏INFORMATION COLUMN

自定义 Forge Viewer 右键菜单(Context Menu)

Harriet666 / 1365人阅读

摘要:前阵子有些圈的朋友们都在询问同一个问题要怎么在的自带右键菜单上添加自定义项目或是只显示自订义项目以下将针对在自带右键菜单上添加自定义项目和只显示自订义项目的右键菜单进行说明。

前阵子有些 Autodesk Forge 圈的朋友们都在询问同一个问题『要怎么在 Viewer 的自带右键菜单上添加自定义项目或是只显示自订义项目』~ 以下将针对『在自带右键菜单上添加自定义项目』和『只显示自订义项目的右键菜单』进行说明。

一、 在自带右键菜单上添加自定义项目:

在自带右键菜单上添加自定义项目是非常容易的,Forge Viewer 提供了一个 API 让使用者可以非常轻易的在自带菜单上添加自个的项目,而你需要做的就是像下面这段代码一样做一个简单的 API 调用。下面这个例子会在右键菜单上添加两个新项目,一个是『改变已选构件的颜色成红色(Override color of selected elements to red)』,另一个是『回复颜色变更(Clear overridden corlor)』:

viewer.registerContextMenuCallback(  "MyChangingColorMenuItems", ( menu, status ) => {
    if( status.hasSelected ) {
        menu.push({
            title: "Override color of selected elements to red",
            target: () => {
                const selSet = this.viewer.getSelection();
                this.viewer.clearSelection();

                const color = new THREE.Vector4( 255 / 255, 0, 0, 1 );
                for( let i = 0; i < selSet.length; i++ ) {
                    this.viewer.setThemingColor( selSet[i], color );
                }
            }
        });
    } else {
        menu.push({
            title: "Clear overridden corlor",
            target: () => {
                this.viewer.clearThemingColors();
            }
        });
    }
});

在执行完上面的代码后就在右键菜单上看到这两个项目:

『改变已选构件的颜色成红色(Override color of selected elements to red)』项目将会在有构件被选中时在菜单上显示:

『回复颜色变更(Clear overridden corlor)』项目会在没有选中任何构件时出现:

但一般情况下,我们会将上面的代码放到一个自定义括展里头,让我们可以灵活的使用:

class MyMenuItemExtension extends Autodesk.Viewing.Extension {
  constructor( viewer, options ) {
    super( viewer, options );

    this.onBuildingContextMenuItem = this.onBuildingContextMenuItem.bind( this );
  }

  get menuId() {
    return "MyColorContextMenu";
  }

  onBuildingContextMenuItem( menu, status ) {
    if( status.hasSelected ) {
      menu.push({
        title: "Override color of selected elements to red",
        target: () => {
          const selSet = this.viewer.getSelection();
          this.viewer.clearSelection();

          // Change color of selected elements to the red
          const color = new THREE.Vector4( 255 / 255, 0, 0, 1 );
          for( let i = 0; i < selSet.length; i++ ) {
            this.viewer.setThemingColor( selSet[i], color );
          }
        }
      });

    } else {
      menu.push({
        title: "Clear overridden corlor",
        target: () => {
          this.viewer.clearThemingColors();
        }
      });
    }
  }

  load() {
    // Add my owned menu items
    this.viewer.registerContextMenuCallback(
      this.menuId,
      this.onBuildingContextMenuItem
    );

    return true;
  }

  unload() {
    // Remove all menu items added from this extension
    this.viewer.unregisterContextMenuCallback( this.menuId );

    return true;
  }
}

Autodesk.Viewing.theExtensionManager.registerExtension( "DemoMenuExtension", MyMenuItemExtension );


二、 只显示自订义项目的右键菜单:

如果上头的代码与你的需求不符合,你可以考虑编写一自订义的右键菜单,一样的他也不会太困难。现在举个例子来说明,像现在如果我想让自带右键菜单上除了自带项目外,还会在点击到不同构件时显示不同的项目;我需要做的就是通过继承 Autodesk.Viewing.Extensions.ViewerObjectContextMenu 和加入 hitTest 相关的逻辑到自定义右键菜单的 buildMenu 函数,就像下面这样:

class MyContextMenu extends Autodesk.Viewing.Extensions.ViewerObjectContextMenu {
  constructor( viewer ) {
    super( viewer );
  }

  isWall( dbId ) {
    //Logics for determining if selected element is wall or not.
    return new Promise( ( resolve, reject ) => {
        $.get(
            "/api/walls/" + dbId,
            ( response ) => {
                if( response && response.id != 0 ) {
                    return resolve( true );
                }
                return resolve( false );
            }
        )
        .error( ( error ) => reject( error ) );
    });
  }

  async buildMenu( event, status ) {
    // Get defulat menu items from the super class
    const menu = super.buildMenu( event, status );

    // Do hitTest to get dbIds
    const viewport = this.viewer.container.getBoundingClientRect();
    const canvasX = event.clientX - viewport.left;
    const canvasY = event.clientY - viewport.top;

    const result = this.viewer.impl.hitTest( canvasX, canvasY, false );

    if( !result || !result.dbId ) return menu;

    let isWall = false;
    try {
        isWall = await this.isWall( result.dbId );
    } catch ( error ) {
        isWall = false;
    }

    if( status.hasSelected && isWall ) {
      menu.push({
          title: "Show current surface temperature map",
          target: () => {
              $.post(
                    "/api/walls/temperature",
                    ( response ) => {
                        ViewerUtil.showWallTemperatureMap( response.values );
                    }
              );
          }
      });
    }

    return menu;
   }

   /**
    * @override
    */
   async show( event ) {
    const numSelected = this.viewer.getSelectionCount();
    const visibility = this.viewer.getSelectionVisibility();
    const status = {
      numSelected: numSelected,
      hasSelected: ( numSelected > 0 ),
      hasVisible: visibility.hasVisible,
      hasHidden: visibility.hasHidden
    };
    const menu = await this.buildMenu( event, status );

    this.viewer.runContextMenuCallbacks( menu, status );

    if( menu && menu.length > 0 ) {
      this.contextMenu.show( event, menu );
    }
   }
}

class MyContextMenuExtension extends Autodesk.Viewing.Extension {
    constructor( viewer, options ) {
        super( viewer, options );
    }

    load() {
        // Use my owned context menu.
        this.viewer.setContextMenu( new MyContextMenu( this.viewer ) );
        return true;
    }

    unload() {
        // Restore default context menu
        this.viewer.setContextMenu( new Autodesk.Viewing.Extensions.ViewerObjectContextMenu( this.viewer ) );
        return true;
    }
}

Autodesk.Viewing.theExtensionManager.registerExtension( "DemoWallMenuExtension", MyContextMenuExtension );

这样子就会在点击到墙构件显示这个项目『Show current surface temperature map』:

相反的,如果你不想显示菜单上自带的项目,你可以改成继承 Autodesk.Viewing.UI.ObjectContextMenu。但你点击到墙构件的时候就只会显示『Show current surface temperature map』这个项目,就像下面这个样子:

希望上面的说明对各位使用 Autodesk Forge 的朋友们有些帮助~

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/89534.html

相关文章

  • Forge Viewer 里加入订义线

    摘要:可能有许多原因你想在里加入自订义的线型,例如显示线框几何视觉化包围箱或者其他你想带给使用者的视觉回馈。下面是我传写的一个例子,他可以在选重构件后在场景里用自定义线型描绘它的包围箱,在线示例可以参考这里 showImg(https://segmentfault.com/img/bVVaUx?w=1794&h=930); 这篇文章的原著是 Autodesk AND 的 Philippe L...

    zilu 评论0 收藏0
  • 使用 Electron 定义菜单

    摘要:使用自定义菜单此系列文章的应用示例已发布于可以或下载后运行查看欢迎使用和模块可用于创建自定义本地菜单有两种菜单应用程序顶部菜单和上下文右键单击菜单在浏览器中打开完整的文档创建应用程序菜单支持进程使用和模块可以自定义你的应用程序菜单如果 使用 Electron 自定义菜单 此系列文章的应用示例已发布于 GitHub: electron-api-demos-Zh_CN. 可以 Clone ...

    MageekChiu 评论0 收藏0
  • Autodesk Forge Viewer 信息本地化技术分析

    摘要:默认情况下,是英文环境,调取的是的资源其实无需翻译。但是,如前面提到的,语言包只是包含了部分常规字串的翻译,如果遇到没有包含的常规字串怎么办呢例如,本例中的语言包并没有对,进行翻译,所以即使切换了语言,它们仍旧是英文。 注:本文是个人调试分析所得,非官方文档,请酌情选用参考。文中分析的数据由https://extract.autodesk.io转换下载而来。 谈到信息本地化,个人觉得包...

    littleGrow 评论0 收藏0
  • 如何在 Forge Viewer 里获取含 Markups 的截图

    摘要:截图据我所知是目前在最常被使用的功能,你可以在官方博客里头找到不少关于这个的文章,但要如何制作含的截图呢要做到这个其实挺容易的,关键在于这个方法,但在调用时必需注意的截图的大小。下面的样例是调用这个方法通过将画在的画布上。 showImg(https://segmentfault.com/img/bV1Cei?w=992&h=490); 截图据我所知是目前在 Forge Viewer ...

    liaoyg8023 评论0 收藏0

发表评论

0条评论

Harriet666

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<