G6 使用入门与总结
这周的工作中,有一个需求需要我去在前端生成一个决策树,于是去考察了很多开源的方案,下面这是我一开始调研的图表,大家可以看一下,根据自己的选择去挑自己合适的,最终我选的是G6。
其实G6的文档已经算是非常不错的了,那我写这篇博客的目的主要有两点:
- 根据自己的使用体验,重新组织成我习惯记忆的方式,方便以后自己查看。
- 总结一下使用过程中踩的几个小坑。
这里吐槽一句,G6对于TypeScript实在是太不友好了,所有的属性都是可选的,有时候写下来一堆问号
组件库 | 上手难度 | 性能 | 自由度/已有方案成熟型 | 备注 |
---|---|---|---|---|
G6 | 文档较为详细:前言 | 节点数少,但是单个节点比较复杂时候比较实用 | 自由度较高,支持自定义节点 | 主要是做图分析 |
X6 | 文档较为详细 快速上手 | 节点多,但是单个简单,且更多的是拖拽等操作时比较实用 | 主要做的是图编辑 | |
ggEditor | 几乎没有文档,也不更新文档了 alibaba/GGEditor | 蚂蚁金服团队基于G6+React封装的,与React兼容较好,但是早已不更新,使用的是3.5版本的G6 | ||
Graphin | 功能概览 | 自由度较低,只支持圆形节点,无法定制且已有方案不符合要求 主要做图分析,而不是图编辑 | 蚂蚁金服团队基于G6+React封装的,与React兼容较好 | |
jointjs | 收费,且license为MPL-2.0 | |||
jsPlumb | 基于Jquery和canvas,大批量操作可能有问题 | 使用上与React有些不搭配 | ||
d3 | 文档比较清晰,但是较为偏底层,所以要实现需求难度较大 | 自由度较高,但是感觉还比较原始,不如X6成熟 | 如果把G6和X6比做arco,这个更像是react | |
spritejs | 文档比较清晰,但是较为偏底层,所以要实现需求难度较大 | 同上 | 同上 |
如何在React中使用G6
一开始我还在GGEditor和G6之间徘徊,因为我的前端项目是基于React的,使用GGEditor可能会方便一点,但是我在G6的官网找到了官方推荐的React中的使用示例,这才决定使用G6,这是官方势力的链接:https://g6.antv.vision/zh/docs/manual/advanced/g6InReact
G6核心概念
这里借用一下官方网站的图片
我来帮大家理一下,这几个核心概念之间的关系:
图
在G6中,主体(objects)与关系(relationships)的组成。它甚至不局限于视觉,主体与关系的数据也可以称为图。在 G6 中,Graph 对象是图的载体,它包含了图上的所有元素(节点、边等),同时挂载了图的相关操作(如交互监听、元素操作、渲染等)。Graph 对象的生命周期为:初始化 —> 加载数据 —> 渲染 —> 更新 —> 销毁。
图形
图形:又叫做Shape,Shape 指 G6 中的图形、形状,它可以是圆形、矩形、路径等。它一般与 G6 中的节点、边、Combo 相关。G6 中的每一种节点/边/ Combo 由一个或多个 Shape 组成。节点、边、Combo、标签文本的配置都会被体现到对应的图形上。
既然每种节点都可以由多个图形组成,那么同一个节点中的所有图形就可以组成一个组,,也就是图形分组,而每个组都有一个关键图形(keyShape),像内置的rect节点的关键图形就是个rect图形。
不过到目前为止,我所接触的分组概念一般是在自定义节点的时候才会用到,等会解释自定义节点的时候会说。
每个图形都有自己的属性,不同的图形有公共的属性,但也有各自独特的属性,公共的属性,比如图的填充色,边框色,边框宽度,阴影颜色,阴影位置等。
单独的属性,如矩形会有宽度和高度,圆会有半径等等。
图形分组 group 类似于SVG 中的 g 是用来组合图形对象的容器。在 group 上添加变换(例如剪裁、旋转、放缩、平移等)会应用到其所有的子元素上。在 group 上添加属性(例如颜色、位置等)会被其所有的子元素继承。此外, group 可以多层嵌套使用,因此可以用来定义复杂的对象。
图形变换则是指的旋转缩放等
布局
布局则是G6自带的一些帮助你安排自动节点位置的布局方式,由于我这次是要生成一个决策树,每个节点的位置需要我自己控制,所以就没有仔细去看,有需要的可以去官网查阅
交互与事件
事件可以分为以下四个层次:
- 画布、图形层次的事件,
mousedown
,mouseup
,click
,mouseenter
,mouseleave
等; - 节点/边 上的事件,
node:mousedown
,edge:click
等,以type:eventName
为事件名称; - 时机事件:
- 节点/边增删改时的事件, 例如:
beforeadditem
,afteradditem
等; - 节点/边状态改变时的事件:
beforerefreshitem
与afterrefreshitem
; - 布局时机:
beforelayout
与afterlayout
。
- 节点/边增删改时的事件, 例如:
如果要了解 G6 支持的所有事件,请参考 Event API。
在事件之上,G6定义了Behavior,其实就是事件及其处理函数的集合,我们从如何自定义一个事件就可以看出来:
1 | G6.registerBehavior('activate-node', { |
当然,G6也有很多内置的事件,比如拖拽节点,拖拽或者缩放画布。
在事件之上,定义了交互模式Mode,每个交互模式就是几个Behavior的集合,如
1 | const graph = new G6.Graph({ |
以上是模式定义的一个例子。在图上定义了两个模式,分别是 default
,edit
。其中 default
包含两个 Behavior:'drag-canvas'
和 'zoom-canvas'
,都使用行为的默认参数。
状态
G6 中的 state,指的是节点或边的状态,包括交互状态和业务状态两种。
在 G6 中,配置交互状态和业务状态的方式是相同的。对于部分只使用 G6 来完成某个需求的开发,而不想深入理解 G6 的用户,其实不用区分交互状态和业务状态的区别,使用相同的方式定义状态,完全没有理解成本。
交互状态
交互状态是与具体的交互动作密切相关的,如用户使用鼠标选中某个节点则该节点被选中,hover 到某条边则该边被高亮等。
G6 中默认处理的是交互状态。
业务状态
指根据用户业务需求自定义的状态。业务状态是与交互动作无关的,与具体业务逻辑强相关的,也可理解为是强数据驱动的。如某个任务的执行状态、某条申请的审批状态等,不同的数据值代表不同的业务状态。业务状态与用户交互动作无关,但在 G6 中的处理方式同交互状态一致。
不论是节点还是边,它们的属性分为两种:
图元素
这次主要用到的就是自定义节点和边,主要就是踩坑,都在下面的总结里了
总结
- 图形属性与节点属性不同,虽然有很多相同配置
- 自定义dom节点,只能在render是svg模式下生效
- 自定义dom节点上的时间,不会被图监听到,而是被自身截获。
- 自定义节点时,在图形分组上第一次调用addShape返回的就是关键shape,同时越往后的shape越靠上,也就是会覆盖在之前的shape上面。