自定义交互 Behavior

阅读时间约 2 分钟

G6 除了提供丰富的 内置交互行为 Behavior 外,还提供了自定义交互行为的机制,方便用户开发更加定制化的交互行为。

在交互行为上, G6 主要考虑了三个场景:

  • 展示关系数据;
  • 可视化建模;
  • 图分析。

在这些场景中只要用户可能无法一眼看清楚所有需要的信息,都需要进行交互,例如:

  • 图太大,需要缩放;
  • 单个节点上展示的信息太少,需要通过 tooltip 显示详情;
  • 对节点进行增删改查。

我们无法将所有常用的交互全部内置到 G6 中。由于场景不一样,业务不一样,同样的目的需要的交互都不一样:

  • 有些系统需要从工具栏上点击后添加节点,有些系统需要从面板栏上拖出出新的节点;
  • 有的业务添加边需要从锚点上拖拽出来,而有些直接点击节点后就可以拖拽出边;
  • 有些边可以连接到所有节点上,而有些边不能连接到具体某个节点的某个锚点上;
  • 所有的交互的触发、持续、结束都要允许能够进行个性化的判定;
  • ……

我们可以看到在图上的交互是繁杂多变的。各种冲突、各种配置项会让用户和开发者疲于应对。出于这些考虑,G6 提供了一套非常简单而灵活的机制来实现交互。

Behavior 的生命周期

为实现交互,首先需要了解交互的生命周期。交互起源于用户在系统上的所有事件,是否允许交互发生同事件密切相关。所以我们看到交互的生命周期,即操作事件的过程如下:

  • 绑定事件;
  • 触发事件;
  • 持续事件;
  • 结束事件;
  • 移除事件。

自定义交互 registerBehavior

通过 G6.registerBehavior 自定义 Behavior。下面代码实现了名为 'activate-node' 的交互行为,在终端用户点击节点时,置该节点的 active 状态为 true;再次点击或点击画布时,置该节点的 active 状态为 false

  ⚠️注意:

  • 下面代码仅设置了不同交互后节点的状态,没有指定这些状态下节点的样式。若需要根据节点状态变化它的样式,参见 配置不同 State 下的节点样式
  • 自定义 Behavior 时,可选的方法请参数 Behavior API
  • getEvent 返回该 Behavior 所需监听事件的对象,G6 中支持的所有事件,请参考 Event API
G6.registerBehavior('activate-node', {
  getDefaultCfg() {
    return {
      multiple: true
    };
  },
  getEvents() {
    return {
      'node:click': 'onNodeClick',
      'canvas:click': 'onCanvasClick'
    };
  }
  onNodeClick(e) {
    const graph = this.graph;
    const item = e.item;
    if (item.hasState('active')) {
      graph.setItemState(item, 'active', false);
      return;
    }
    // this 上即可取到配置,如果不允许多个 'active',先取消其他节点的 'active' 状态
    if (!this.multiple) {
      this.removeNodesState();
    }
    // 置点击的节点状态 'active' 为 true
    graph.setItemState(item, 'active', true);
  },
  onCanvasClick(e) {
    // shouldUpdate 可以由用户复写,返回 true 时取消所有节点的 'active' 状态,即将 'active' 状态置为 false
    if (this.shouldUpdate(e)) {
      removeNodesState();
    }
  },
  removeNodesState() {
    graph.findAllByState('node', 'active').forEach(node => {
        graph.setItemState(node, 'active', false);
      });
  }  
});

使用自定义的 Behavior

有了上面代码定义的名为 'activate-node' 的 Behavior 以后,在实例化 Graph 时,在 modes 中将其配置到默认或其他行为模式中。下面代码将其配置到了默认行为模式中,在默认模式下,该行为将会生效。

const graph = new G6.Graph({
  container: 'mountNode',
  width: 500,
  height: 500,
  modes: {
    // 定义的 Behavior 指定到这里,就可以支持 Behavior 中定义的交互
    default: ['activate-node'],
  },
});