缘起

原本 G6 是不关注内部节点的布局的,所以 Graph 并不集成各种 Layout 而将布局视为数据预处理的一部分。这在 TreeGraph 中并不适用,因为树图的一系列操作,例如展开,折叠,新增,删除节点,都涉及到布局的刷新,如果在外部实现,编程体验很不好,但是又不想限制用户使用的布局工具,于是开了 layout 配置项,由内部自行调用布局。但是随着业务场景的增加,这种方式的弊端就展露出来了:

  • 设置节点样式不 work?很多 layout 都是生成一份新数据的,这样用户在源数据中定义的样式,配置等均不生效了,需要在 render 后获取节点和边,自行修正 model 后刷新视图。
  • 不能在外部自行刷新布局:外部自行刷新布局后,需要用 changeDataupdateItem 等传入,改变了源数据后,与默认的交互行为 collapse-expand 无法协同合作。
  • 只有changeData, refresh 的时候有动画,一般期望有全局的动画开关,若开关打开只要布局更新了就会有动画。

重构思路

主要是内部集成布局算法,根据算法返回结果渲染数据,定义动画。

  • 内部集成布局算法 @antv/hierarchy ,layout 以配置项的形式传入。同时兼容之前 function 形式传入。这个感觉可以在下个大版本优化掉,仅支持 config 形式。 ```javascript const graph = new G6.TreeGraph({ layout(data) { … return readyData; } animate: true, animateCfg: { … } });

const graph = new G6.TreeGraph({ layout: { type: ‘compactBox’, getHeight(node) { … }, getWidth(node) { … } } }); ```

  • 之前会渲染源数据的全量数据,然后根据layout去更新节点位置。现在改为根据布局完的结果数据做渲染,提升性能的同时不需要关注两份数据之间的差异。

  • 将树的更新动画从 collapse-expand 下沉到 TreeGraph 上,用户只需要维护一份 animate 配置。 collapse-expand 行为仅是监听事件,调用 layout 方法,更新树图即可,职责更明确。

  • 添加增/删/改树节点方法。由于此算法会将源数据作为数据项存储在结果数据中,直接使用结果数据不行,需要包一层。

    • addChild: 根据布局后的结果数据得到正确的节点模型,创建节点,连线。
    • updateChild: 根据源数据变更,更新视图节点。可能会涉及子树添加,子树删除。并涉及动画操作。添加时考虑从父节点运动到子节点真实位置的动画,删除时考虑从子节点运动到父节点后删除动画。

note: G6 ~3.0.4 版本已经完成上述重构,API 和使用方法已同步更新至 TreeGraph