1

这礼拜的小技巧是关于如何以不加入太多的 JavaScript 的方式自订义 ModelStructurePanel 的交互行为,这个小技巧受到这篇问与答的启发:Prevent zoom in Forge viewer when clicking in Model Browser

在官方释出 3.2.1 版 Viewer 的同时发布了新版本的 ModelStructurePanel,这个面版已被整个重新改写,这次更新也加入一些新的交互行为,下面我们将会稍作解释。那回到主题,如果想要自定义用户点击面板上节点时的行为时要怎么做呢?

图片描述

但在开始自定这些交户行为前,我们先来看看 Autodesk.Viewing.Extensions.ViewerModelStructurePanel Viewer3D.js 里是如何被实作的。首先看 onClick 的部份,我们可以看到这个方法会去检查辅助按键 [Ctrl, Shift, Alt] 并将其加到事件里头,所以我们可以通过组合点击(click)和这些辅助按键的方式来实作、处理不同的交互行为。

ViewerModelStructurePanel.prototype.onClick = function (node, event) {

  if (this.isMac && event.ctrlKey) {
    return;
  }

  var that = this;

  var key = "click";

  if (that.ctrlDown(event)) {
    key += "Ctrl";
  }

  if (event.shiftKey) {
    key += "Shift";
  }

  if (event.altKey) {
    key += "Alt";
  }

  if (this.clickConfig && this.clickConfig[key]) {

    that.handleAction(this.clickConfig[key]["onObject"], node);

  } else {

    this.viewer.select(node);
  }
};

同时,如果上头代码里的 key 与 clickConfig 有匹配,这个方法会去调用 handleAction 这个函数;而这个 clickConfig 就是用来订义 ModelStructurePanel 点击交互行为的设置对象,它会在面板初始化时被带入。

var kDefaultDocStructureConfig = {
  "click": {
    "onObject": ["toggleLeavesSelection"]
  },
  "clickShift": {
    "onObject": ["toggleMultipleLeavesSelection"]
  },
  "clickCtrl": {
    "onObject": ["toggleMultipleLeavesSelection"]
  }
};

function ViewerModelStructurePanel(viewer, title, options) {

  // ... skipping stuff for clarity ...

  this.clickConfig = (options && options.docStructureConfig) 
      ? options.docStructureConfig 
      : kDefaultDocStructureConfig;

这边是 ` 这个函数的实作,我们可以从这边看到 ModelStructurePanel` 有哪些默认的交互行为:

ViewerModelStructurePanel.prototype.handleAction = function (actionArray, dbId) {

  for (var action in actionArray) {
    switch (actionArray[action]) {
      case "toggleLeavesSelection":
        toggleLeavesSelection(this, dbId);
        break;
      case "toggleMultipleLeavesSelection":
        toggleMultipleLeavesSelection(this, dbId);
        break;
      case "selectOnly":
        this.ignoreNextSelectionChange = true;
        this.viewer.select(dbId);
        break;
      case "deselectAll":
        this.ignoreNextSelectionChange = true;
        this.viewer.select([]);
        break;
      case "selectToggle":
        this.ignoreNextSelectionChange = true;
        this.viewer.toggleSelect(dbId);
        break;
      case "isolate":
        this.viewer.isolate(dbId);
        break;
      case "showAll":
        this.viewer.isolate(null);
        break;
      case "focus":
        this.viewer.fitToView();
        break;
      case "hide":
        this.viewer.hide(dbId);
        break;
      case "show":
        this.viewer.show(dbId);
        break;
      case "toggleVisibility":
        this.viewer.toggleVisibility(dbId);
        break;
    }
  }
};

讲到这边你可能会问,到底要怎么自订这些点击交互行为呢?这其实颇容易的~基于上面讲述的内容,你可以通过下面的代码在 Forge Viewer 触发 Autodesk.Viewing.OBJECT_TREE_CREATED_EVENT 事件时,将产生一个新的 ModelStructurePanel 取代 Forge Viewer 默认的那一个。

备注:对 Forge Viewer 有些熟悉的朋友可能知道,默认的 ModelStructurePanel 是在这个事件触发时被建立的。

viewer.addEventListener(Autodesk.Viewing.OBJECT_TREE_CREATED_EVENT, function() {

    var options = {
      docStructureConfig: {
          click: {
              onObject: ["selectOnly"] //instead of toggleOverlayedSelection
          },
          clickShift: {
            onObject: ["isolate"] //instead of toggleMultipleOverlayedSelection
        },
          clickCtrl: {
          onObject: ["selectToggle"] //instead of toggleMultipleOverlayedSelection
        }
      }
    }

    var customModelStructurePanel =
      new Autodesk.Viewing.Extensions.ViewerModelStructurePanel(
        viewer, 'Browser', options)

    viewer.setModelStructurePanel(customModelStructurePanel)
  })

最后,当然如果 ModelStructurePanel 自带的交互行为不满足你的需求时,你也可以将整个 ModelStructurePanel 复制出来,在 handleAction 这个方法里头加入自个的交互内容。如果不知道如何开始,你可以参到这篇英文博客:Supporting multiple models in the new ModelStructurePanel


康益昇
748 声望103 粉丝