G6-笔记
快速开始
安装
npm install --save @antv/g6
快速使用
- 创建Graph的HTML容器。
- 数据准备
- 创建Graph实例
- 数据配置和渲染
<!-- step1 -->
<div id="container"></div>
<script type="module">
import G6 from '@antv/g6';
// step2 数据
const datas = {
nodes: [
{ id: 'node1', x: 100, y: 200, },
{ id: 'node2', x: 300, y: 200, }
],
edges: [
{ source: 'node1', target: 'node2', }
]
}
// step3 创建实例
const graph = new G6.Graph({
container: 'app',
height: 400,
width:600,
})
// step4 数据读取和渲染
graph.data(datas);
graph.render();
</script>
G6.Graph
const graph = new G6.Graph(Config)
生命周期
图的生命周期:初始化 -> 加载数据 -> 渲染 -> 更新 -> 销毁。
配置
{
container: 'idRef', // 指定图挂载的容器 必要配置项
height: 400, // 图的高度 必要配置项
width: 500, // 图的宽度 必要配置项
renderer: 'canvas', // 默认canvas,可选svg; 注意svg性能较差
fitView: true, // 设置是否将图适配到画布中
fitViewPadding: [20, 40, 50, 20], // 画布上四周的留白宽度,和CSS的padding一样,fitView为true生效
fitCenter: false, // 默认false,是否平移图使其中心对齐画布中心
animate: false, // 是否启用全局动画。
layout: { // 布局对象属性
type: 'force', // 布局类型
},
modes: { // 定义各种模式
default: ['drag-canvas', 'zoom-canvas', 'drag-node'],
edit: []
},
nodeStateStyles: { // 配置节点不同状态的样式
hover: { // 鼠标hover上节点,即hover状态为true时的样式
fill: 'lightsteelblue'
}
},
edgeStateStyles: { // 配置边不同状态的样式
click: { // 鼠标点击边,即click的状态为true时的样式
stroke: 'steelblue'
}
},
groupByTypes: true, // 默认值为㹖
}
fitView
图上有些节点的坐标不在图的高宽范围内,会被截掉不显示,只能看到部分内容,设置fitView为true,可以将所有内容适配到图中。
Layout
当前数据中没有节点位置信息,或数据中的位置信息不满足需求时,需要借助一些布局算法对图进行布局。G6提供了9种一般图和4种树图的布局。
默认布局,当实例化图没有配置布局时:
- 若数据中节点有配置信息(x 和 y),则按钮归数据的位置信息进行绘制;
- 若数据中节点没有位置信息,则默认使用一般图中的一种Random Layout进行布局。
布局在调用graph.render()时执行计算
Modes
这是一个对象,可以定义各种模式,每种模式有不同的行为。 如默认模式default下,可以有drag-canvas, zoom-canvas, drag-node三种内置交互行为,而edit为空,没有可用的交互行为。 通过graph.setMode(modeValue)来切换模式。
groupByTypes
为true时,所有节点在一个名为nodeGroup的分组,所有边在另一个名为edgeGroup的分组,且nodeGroup在edgeGroup上层。 设置为false后将不存在 nodeGroup和edgeGroup,所有节点和边在同一个分组,它们的层级根据生成的顺序决定。
方法
graph.data
读取数据,参数是一个数组;要在render函数之前使用
graph.render
直接渲染图
graph.read(data)
接入数据,并进行渲染。功能相当于data和render方法的结合。
graph.setItemState
修改元素的状态
graph.on('node:mouseleave', (e) => {
const nodeItem = e.item; // 获取鼠标进入节点的元素对象
graph.setItemState(nodeItem, 'hover', false)
})
graph.setItemState(elementItem, stateName, false|true)
graph.clearItemStates
取消graph.setItemState设置的状态,支持一次取消单个或多个状态。
graph.clearItemStates(item, 'selected')
graph.clearItemStates(item, ['selected', 'active'])
graph.findAllByState
获取某元素下某种状态的所有元素,如graph.findAllByState('node', 'click')为获取当前图状态click为true的所有节点。
graph.findAllByState('combo|node|edge|vedge', 'stateName');
graph.update/graph.updateItem
此方法用于动态更新节点或边的keyShape。
graph.updateItem(node, {
style: {
stroke: 'blue
}
})
graph.updateLayout(string|object)
参数是字符串,或参数包含type字段的对象,且与之前的布局方法不同时会更换布局。 参数对象不含type或type字段值与之前的布局方法名称一样,布局方法不变,只修改参数。
graph.changeData()
更改数据源,根据新的数据重新渲染视图。
graph.setMode()
切换交互模式
元素及其配置
图的元素(Item)包含图上的节点node、边edge和Combo三大类。每个图元素由一个或多个图形(Shape)组成,且都会有自己唯一关键图形(keyShape)。
除了G6内置的节点node、边edge和combo外,还可以自由搭配图形和组合图形达到自定义节点、边和combo的目的。不同内置元素的主要区别在于元素的图形Shape,例如:圆形,矩形,图片等
元素属性
不论元素的节点还边,它们的属性分为两种:
- 样式属性style: 对应Canvas中的种样式,在元素状态State发生变化时,可以被改变。
- 其他属性:如图形类型(type)、id一类元素状态State发生变化时不能被改变的属性。
如图的节点被click或hover时,造成节点状态的变化,只能自动改变节点对应状态的样式如fill, stroke等。 其他属性可以通graph.updateItem手动配置。 样式属性都在style对象中,和其他属性字段并行。
配置属性
可以根据不同场景需求使用不同方式配置
- 实例化图时配置元素的全局属性。在G6.Graph中配置,这是全局生效的,优先级最低,可以被其他方式覆盖如数据中的配置。defaultNode配置节点,defaultEdge配置边,其他数据结构和数据中配置的结构是一样的。这种方式适用于全局配置。
- 数据中配置,在graph.data的参数中配置,参数对象里的节点和边。这方式适用个性化配置。
图形Shape
G6中的每个节点、边和Combo都是由一个或多个图形Shape组件。节点、边、Combo、标签文本的配置都会被体现到对应的图形上。 图形Shape有很多,有图形(rect, circle,ellipse)、文本、锚点等。
关键图形KeyShape
虽然元素有若干个图形组成,但只有一个关键图形(keyShape)。 keyShape是在节点、边和Combo的draw()方法或drawShape()方法中返回的图形对象。 主要用交互检测、样式随状态自动更新。也就是说元素的style和stateSyles的配置只能体现在keyShape上,其他图形需要另行配置,如文本图形需要在labelCfg上配置。
包围盒确定
节点、Combo的包围盒决定了相关边的连入点(与相关边的交点)。keyShape不同,节点与边的交点计算结果不同。
Shape生命周期
大体分为:初始化渲染、更新、操作、销毁。 绘制:画图形。使用draw(cfg, group),提供了配置项和图形容器,必须返回图形作为keyShape。 更新:数据变更导致Shape及文本变化。使用,update(cfg, n)。 操作:给Shape添加状态,如selected等。使用setState(name, value, item)。
图形Shape及其属性
G6的元素(节点、边和Combo)是由一个或多个图形Shape组成,主要通过自定义节点或自定义边时在draw方法使用group.addShape添加。G6支持以下的图形Shape:
- circle:圆;
- rect:矩形;
- ellipse:椭圆;
- polygon:多边形;
- fan:扇形;
- image:图片;
- marker:标记;
- path:路径;
- text:文本;
- dom(svg):DOM(图渲染方式 renderer 为 'svg' 时可用)。
Shape通用方法
attr(name)
获取实例的属性值
const width = shape.attr('width');
attr(name, value)
更新实例的单个绘图属性
attr({...})
批量更新实例绘图属性
rect.attr({
fill: '#999',
stroke: '#666',
})
Shape用法
这里以图片图形Image为主,其它的可以查看官网内容
group.addShape('image', {
attrs: {
x: 0,
y: 0,
img: 'https://g.alicdn.com/cm-design/arms-trace/1.0.155/styles/armsTrace/images/TAIR.png'
},
// 在 G6 3.3 及之后的版本中,必须指定 name,可以是任意字符串,但需要在同一个自定义元素类型中保持唯一性
name: 'image-shape'
})
图形分组Group
和Combo区别
图形分组Group与节点分组Combo属于不同层次的概念。
- 图形分组针对图形Shape层次的分组
- 节点分组Combo是针对节点的分组,与数据结构中的层次、分组对应。
概念
图形分组相当于一个容器,包含了多个图形,在分组上添加变换(剪裁、旋转、平移)会应用到其所有的子元素上,添加属性(颜色、位置)会被所有子元素继承,且分组可以多层嵌套。 G6中一个实例所有节点同属于一个变量名为nodeGroup的分组,所有边同属于一个变量名为edgeGroup的分组,且节点的分组层级(zindex)在高于边的分组。
用法
获取元素Group
// 获取元素(节点、边、Combo)的图形对象的容器
const group = item.getContainer();
// 等价于
const group = item.get('group')
addGroup(cfgs)
向分组中添加新的分组。
const subGroup = group.addGroup({
id: 'rect'
})
addShape(type, cfgs)
向分组中添加新的图形
const keyShape = group.addShape('rect', {
attrs: {
stroke: 'red',
},
name: 'rect-shape'
})
获取图形group.get('children')
这个方法返回的是一个数组,里面的元素是图形,排序是按照addShape方法添加的顺序
const group = node.getContainer(); // 获取容器
const shape = group.get('children')[0]; //获取第一个添加的图形
在分组上添加clip、transform等会影响到该分组中的所有元素(子分组或图形)
图的交互Behavior
图的交互是指对元素的hover,click、画布的放缩、拖拽后产生的状态变化而对元素相对就的状态样式进行自动修改。
交互行为Behavior
定义图上的交互事件机制,与交互模式Mode搭配使用。G6内置了一系列交互行为,用户可以直接使用。如:
- drag-canvas: 拖拽画布
- zoom-canvas: 缩放画布
交互管理Mode
Mode是G6交互行为的管理机制,一个Mode是多种行为Behavior的组件,用户通过切换不同模式(Mode)进行交互行为管理。
交互状态State
状态State是G6中的状态机制。用户可以为元素(节点、边)设置不同状态对应不同的样式,在状态发生变化时,G6自动更新元素对应状态设置的样式。
如对节点设置状态click为true或false,并为节点设置click的样式为加粗节点边框。当click状态切换为true时,节点的边框会被加粗,click状态切换为false时,节点样式恢复到默认。
实际上,任何操作如,clikk, hover,都可以称为一种状态,当前也可以自定义状态名称,用户可以自由设置不同状态下的元素样式。 要达到交互更改元素样式,需要两步:
- 设置各种状态下的元素样式;
- 监听事件并切换元素状态。
设置元素状态的样式
实例化图时,通过nodeStateStyles和edgeStateStyles两个配置项可以配置在不同状态下的样式。
监听事件切换元素状态
G6所有元素监听都挂载在图实例上,通过graph.on()函数监听某元素类型(node/edge)的某种事件(click, mouseenter, mouseleave)。并在监听函数里使用graph.setItemState()改变元素的状态。
// graph.on('元素类型[node|edge]:事件名', (e) =>{})
graph.on('node:mouseenter', (e) => {
const nodeItem = e.item; // 获取鼠标进入节点的元素对象
graph.setItemState(nodeItem, 'hover', true)
})
事件
G6上所有的事件都需要在graph上监听。
全局事件
只要在画布上范围内发生均会被触发,如:mousedown, mouseup, click, mouseenter, mouseleave等
canvas事件
只在canvas空白片被触发,如canvas:mousedown, canvas:click等,以canvas:eventName为事件名称
节点/边/combo上的事件
例如node:mousedown, edge:click, combo:click等, 以type:eventName为事件名称。
图形上的事件
指定图形上的事件,如circle-shape:mousedown, circle-shape:click等,以shapeName:eventName为事件名称。可以用于绑定节点/边/combo中对局部图形做出响应的场景。
时机事件
时机事件指渲染、视口变换、元素增删改、数据变换等时机。如beforeadditem, afteradditem等。
自定义事件
可以任意位置通过graph.emit(customEventName: string, event: IG6GraphEvent)触发一个事件,第一个参数为自定义事件名称。在触发前,通过graph.on(customEventName: string, callback: Function)进行监听。
内置Behavior
- drag-combo
拖动combo
Collapse-expand-combo 收起和展开combo。若图配置有布局,则该behavior被触发后会触发图的重新布局,可以通过配置去掉这种默认行为。
Drag-canvas 拖拽画布
Scroll-canvas 滚动画布
zoom-canvas 滚动画布
drag-node 拖拽节点,或拖动combo中的节点
Click-select 点击选中节点,再次点击或点击canvas取消选中状态。
Tooltip 节点文本提示
Edge-tooltip 边文本提示
Activate-relations 当鼠标移到某节点时,突出显示该节点以及其直接关联的节点和连线
Brush-select 拖动框选节点
Lasso-select 自由圈选
Collapse-expand 只适用于树图,展开或收起子树。
Create-edge 通过交互创建边
Shortcuts-call 允许终端用户使用键盘组合键调用graph的函数。
自定义交互behavior
生命周期如下:
- 绑定事件
- 触发事件
- 持续事件
- 结束事件
- 移除事件
import G6 from "@antv/g6";
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.setItemStete(item, 'active', false);
return;
}
if (!this.multiple) {
this.removeNodesState();
}
graph.setItemStete(item, 'active', true)
},
onCanvasClick(e) {
},
removeNodesState()
})
插件与工具
G6提供了一些辅助工具,一部分是插件工具,一部分是交互工具。
插件工具
插件工具在实例化的配置plugins的字段里添加。如缩略图插件和背景网格插件引入如下:
// 缩略图
const minimap = new G6.Minimap({
size: [100, 100],
className: 'minimap',
type: 'delegate'
})
// 网格
const grid = new G6.Grid();
const graph = new G6.Graph({
plugins: [minimap, grid ],
// ... 其他配置
})
- 缩略图 (Minimap) 是一种常见的用于快速预览和探索图的工具,可作为导航辅助用户探索大规模图。
- 网格可用于辅助用户在拖拽节点时对齐到网格。
交互工具
交互工具实际是一种交互行为,也就是说在实例化的配置modes可用行为模式里配置即可。 如节点悬浮提示框tooltip,边悬浮提示框edge-tooltip。在modes里配置使用即可。根据官网提示,这两种提示框返回的都是一个div标签,可以使用g6-tooltip为节点和边的悬浮提示框设置一样的样式。如果需求自定义边和节点的可以在返回内容里包含一个带不同class的标签容器。
const graph = new G6.Graph({
modes: {
default: [
'drag-canvas', 'zoom-canvas', 'drag-node',
{
type: 'tooltip',
formatText(model) {
console.log(model)
return 'label: ' + model.label + '<br /> class: '+ model.class;
}
},
{
type: 'edge-tooltip',
formatText(model) {
// 边提示框文本内容
return 'source: ' + model.source + '<br/> target: ' + model.target + '<br/> weight: ' + model.weight;
},
}
],
edit: []
},
})
内置工具
Legend 图例插件。用于说明图中不同类型的节点和边所代表的含义,并可以通过与图例的交互做简单的高亮和过滤。
SnapLine 对齐线插件。
Grid Grid插件在画布上绘制了网格。
Minimap 用于快速预览和探索图的工具
Image Minimap 对于Minimap插件的优化版
Edge Bundling 在关系复杂、繁多的大规模图上,通过边绑定可以降低视觉复杂度。
Menu 用于配置节点上的右键菜单
Toolbar 集成了以下常见的操作:
重做
撤销
放大
缩小
适应屏幕
实际大小
ToolTip 主要用于在节点和边上展示一些辅助信息,G6 4.0以后,Tooltiop插件将会替换Behavior中的tooltip。
Fisheye Fisheye鱼眼放大镜为focus+context的探索场景设计的,它能够保证在放大关注区域的同时,保证上下文以及上下文与关注中心的关系不丢失。
Edge Filter Lens 边过滤镜可以将关注的边保留在过滤镜范围内,其他边将在该范围内不显示。
TimeBar 内置了三种形态的TimeBar组件:带有趋势图的、简易版的、刻度的。
节点
内置节点
G6 的内置节点包括 circle,rect,ellipse,diamond,triangle,star,image,modelRect,donut(v4.2.5 起支持)。
配置方法
支持三种配置方式:实例化图时全局配置,优先级最低、在数据中动态配置、使用graph.node(nodeFn)函数配置,优先级最高。id、label只能配置在每个节点的数据,其他属性三种配置都支持。
实例化图时全局配置
实例化图时通过defaultNode属性配置节点,这里是全局配置,在所有节点上都会生效
在数据中动态配置
既是传给graph.data函数参数的数据对象的属性nodes中的数据。
使用graph.node
该方法可以为不同节点进行不同的配置。
提示
- 必须在render之前调用,否则不起作用。
- 该方法优先级最高,可能会覆盖其他节点的配置,这会造成一些其他配置不生效的疑惑。
- 该方法在增加元素、更新元素时会被调用,如果数据里大,每个节点需要更新的内容多时,可能会有性能问题。
graph.node((node) => {
return {
id: node.id,
type: 'rect',
style: {
fill: 'blue'
}
}
})
方法
nodeItem.toFront()
将节点实例nodeItem提前到其父级group的最前面
nodeItem.toBack()
将节点实例nodeItem放置到其父级group的最后面
nodeItem.show()
显示节点,调用后设置visible为true
nodeItem.hide()
隐藏节点,调用后设置visible为false
lock()
锁住节点。锁住后,拖动节点没有任何反应。但是拖动画布时,还是会有影响的。如果要不影响要自定义behavior的方法来实现。 https://g6.antv.antgroup.com/manual/middle/elements/methods/lock-node
unlock()
解锁节点
hasLocked()
判断当前节点是否上锁
配置
配置内容如下
{
id: 'node1', // 节点的唯一标识 必填
type: 'circle', // 元素的图形,默认为circle
size: 40, // 元素的大小
x: 200, // 节点的横坐标
y: 300, // 节点的纵坐标
label: 'text', // 节点显示的本文
visible: true, // 控制初次渲染显示隐藏,false为隐藏
labelCfg: { // 标签配置属性
position: 'center' // 标签在元素中的位置
style: { // 标签样式属性对象,和标签其他属性并行
fontSize: 12, // 标签的样式属性,文字字体大小
// ...
}
},
style: { // 样式属性对象,和元素其他属性并行
fill: '#000', // 样式属性,元素的填充色
stroke: '#888', // 元素的描边色
// ... 其他样式属性
},
anchorPoints: [0, 0], //指定边连入节点的位置(相对于该节点而言),可以为空
linkPoints:{ // 指定节点周围【上下左右】四个方向上的四个小圆点。
}
}
linkPoints:
anchorPoints是真正用于指定该节点相关边的连入位置的数组,而linkPoints仅是指定是否绘制出四个圆点,不直实际的连接相关边的作用。
自定义节点
通过G6.registerNode(typeName: string, nodeDefinition: object, extendedNodeType?: string)进行自定义节点。 typeName: 新节点类型名称。
extendedNodeType: 被继承的节点类型,可以内置的也可以自定义的,不指定则不继承其他类型节点。 注意:若指定继承节点类型,且在nodeDefinition中没有复写draw, update, setState等必要函数时,将会继承extendedNodeType中的相关定义。这可能会导致一些意外的问题。
Q:节点/边更新时,没有按照在 nodeDefinition 中自定义实现的 draw 或 drawShape 逻辑更新。例如,有些图形没有被更新,增加了没有在 draw 或 drawShape 方法中定义的图形等。
A:由于继承了 extendedNodeType,且在 nodeDefinition 中没有复写 update 方法,导致节点/边更新时执行了 extendedNodeType 中的 update 方法,从而与自定义的 draw 或 drawShape 有出入。可以通过复写 update 方法为 undefined 解决。当 update 方法为 undefined 时,节点/边的更新将会执行 draw 或 drawShape 进行重绘。
import G6 from "@antv/g6";
G6.registerNode(
'nodeName', {
options: {
style: {},
stateStyles: {
hover: {},
selected: {},
}
},
/**
* 绘制节点,包含本文
* @param {Object} cfg 节点的配置项
* @param {G.Group} group 图形分组,节点中图形对象的容器
* @return {G.Shape} 返回一个绘制的图形作为keyShape,通过node.get('keyShape') 可以获取。
*/
draw(cfg, group) {},
/**
* 绘制后的附加操作,默认没有任何操作
* @param {Object} cfg 节点的配置项
* @param {G.Group} group 图形分组,节点中图形对象的容器
*/
afterDraw(cfg, group) {},
/**
* 更新节点,包含文本
* @override
* @param {Object} cfg 节点的配置项
* @param {Node} node 节点
*/
update(cfg, node) {},
/**
* 更新节点后的操作,一般同afterDraw配合使用
* @override
* @param {Object} cfg 节点的配置项
* @param {Node} node 节点
*/
afterUpdate(cfg, node) {},
/**
* 响应节点的状态变化,也就是说哪个节点的状态属性变化了,会觖发当前函数
* 在需要使用动画来响应状态变化时需要被复写
* @param {String} name 状态名称
* @param {Object} value 状态值
* @param {Node} node 节点
*/
setState(name, value, node) {},
/**
* 获取锚点(相关边的连入点)
* @param {Object} cfg 节点的配置项
* @return {Array|null} 锚点(相关边的连入点)的数组,如果为null则没有控制点
*/
getAnchorPoints(cfg) {},
},
// 继承内置节点类型的名字,例如基类 'single-node',或'circle', 'rect'
// 不指定则不继承任何类型节点
'extendNodetype'
)
注意:
- extendedNodeType不写,draw方法是必须的。
- 节点内部所有图形的坐标系是相对于节点本身的坐标,即(0,0)是该节点的中心。而节点的坐标是相对于画布的,由该节点group上的矩阵控制。
- update方法未定义时:若指定了extendedNodeType,则节点更新时执行继承节点类型的update方法逻辑;若未指定extendedNodeType时,则节点更新时会执行draw方法,所有图形清除重绘。
- 指定update方法,不论是否指定extendedNodetype,节点更新时都会执行复写的update函数逻辑。
- afterDraw,afterUpdate方法一般用于扩展已有节点,例如,在矩形节点上附加图片,圆节点增加动画等;
- setState只有在需要使用动画的方式响应状态变化时需要复写,一般的样式响应状态变化可以通过配置状态样式实现
- getAnchorPoints方法仅在需要限制与边的连接点时才需要复写,也可以数据中直接指定。
优化性能
根据上面注意事项3和4,如果存在性能问题,可以通过重写update方法,找到需要更新的shape进行更新,从而优化性能。
节点的连接点
节点的连接点anchorPoint指的是边连入节点的相对位置,即是节点和边的交点位置。 anchorPoint是一个二维数组,每一项都是一个连接点,只有定义了才会有连接点,不定义的是不存在的,在一个图形Shape中,连接点的位置如下,x和y方向上范围都是[0, 1]:
节点定义了anchorPoint之后,边通过sourceAnchor指定anchorPoint数组中的索引作为连接交点的起点,通过targetAnchor指定anchorPoint数组中的索引作为连接交点的终点。
边
内置边:
- line:直线,不支持控制点;
- polyline:折线,支持多个控制点;
- arc:圆弧线;
- quadratic:二阶贝塞尔曲线;
- cubic:三阶贝塞尔曲线;
- cubic-vertical:垂直方向的三阶贝塞尔曲线,不考虑用户从外部传入的控制点;
- cubic-horizontal:水平方向的三阶贝塞尔曲线,不考虑用户从外部传入的控制点;
- loop:自环。
配置方法
和节点一样,有全局配置,数据中配置和使用graph.edge(edgeFn)三种配置方法
配置
配置内容如下
{
source: 'node1', // 起始节点的ID 必填
target: 'node2', // 结束节点的ID 必填
label: 'label', // 边上显示的文本
type: 'line', // 默认为line,内置边
sourceAnchor: 0, // 边的起始节点上的锚点的索引值
targetAnchor:0, // 边的终止节点上的锚点的索引值
style: { // 边的样式
lineAppendWidth: 1, // 边响应鼠标事件检测的宽度,
endArrow: false|Object, // true边的终点绘制默认箭头, 也可以对象自定义
startArrow: false|Object, // true边的起点绘制默认箭头, 也可以对象自定义
// ... 其他一样
},
label: '', //文本文字,没有不显示
labelCfg:{// 文本配置项
refX: 0, // 标签在x方向的偏移量
refY: 0, // 标签在y方向的偏移量
position: 'middle', //文本相对于边的位置,目前支持的位置有:'start','middle','end'。默认为'middle'。
autoRotate: false, // 标签文本是否跟随边旋转, 默认false
style:{}, // 标签样式
},
}
方法
edgeItem.toFront() 将边edgeItem提前到其父级group的最前面
edgeItem.toBack() 将边edgeItem放置到其父级group的最后面
edgeItem.show() 显示边,调用后设置visible为true
edgeItem.hide() 隐藏边,调用后设置visible为false
内置类型
- polyline
// 独有的配置
{
routeCfg: {// 用以配置路由计算的参数,不存在controlPoints时生效
gridSize: 10, // 计算拆线的网格大小,值越小性能消耗越高
maxAllowedDirectionChange: Math.PI / 2, // 允许的最大转角角度, 弧度制
obstacles: [], // 需要躲避的障碍节点对象
},
style: {
radius: 1, // 拐弯处的圆角弧度
offset: 5, // 拐弯处距离节点最小距离
},
controlPoints: [{x: 10, y: 10}, ...], // 其他边也有这个,不指定时根据
}
obstacles
不支持自动躲避所有节点,只能通过例如graph.updateItem(edge, { routeCfg: { obstacles: [graph.findById('node1')]}})的方式手动增加
controlPoints
其他边也有这个,不指定时根据算法自动生成,若指定时,根据指定的坐标进行弯折,坐标是根据画布定位的,一个坐标对应一个折点。
- 自定义边
- 自定义箭头
Combo
Combo是对节点进行分组。内置的combo有两种,circle和rect 两种。 使用combo时,必须在实例化图时配置groupByTypes设置为false,图中元素的视觉层级才能合理。
配置
使用combo时,在数据中,和nodes、edges同一层级加上combos,是一个数组,每个数组元素是combo的配置,如下:
{
id: '', // 唯一标识,也是其他节点归类combo引用的字段,comboId
type: '', // combo的类型,默认为circle.
parentId: '', // 该combo的父combo的ID
padding: number|number[], // 内边距
size: number|number[], // combo的最小尺寸(非固定尺寸),circle为20,rect为[20, 5]
fixSize: number|number[], // 固定尺寸
fixCollapseSize: number|number[], // 折叠时的尺寸
collapsed: false, // 该combo是否收起,如果渲染前配置true,初次渲染时将默认收起
label: '', // combo的文本标签
style:{ // 样式配置项
},
labelCfg: { // 文本标签的样式配置项
},
collapsedSubstituteIcon: {// v4.6.8起支持,combo收起状态下展示的图片
},
}
fixSize
不指定时combo大小由内部元素的分布和大小来决定。若指定了fixSize,而没有指定fixCollapseSize时,combo即时是收起折叠状态仍然保持fixSize的尺寸。
fixCollapseSize
固定该combo折叠收起时的尺寸。不指定时,若未指定fixSize则由size决定收起时的尺寸,否则统一为fixSize尺寸
配置方法
和节点一样,有全局配置,数据中配置和使用graph.combo(edgeFn)三种配置方法
Combo交互
和其他交互一样的配置,内置的combo交互有三种:drag-combo, collapse-expand-combo, drag-node
自定义combo
和节点一样,通过G6.registerCombo('comboName', options, expendedComboName)进行自定义扩展内置的Combo。 自定义时需要以下两点
- 控制combo的生命周期
- 解析用户输入的数据,在图形上展示
import G6 from "@antv/g6";
G6.registerCombo(
'comboName',
{
/**
* 绘制Combo中的图形,不需要为默认的label增加图形,父类方法会自动增加label
* @param {Object} cfg Combo的配置项
* @param {G.group} group 图形分组, Combo中的图形对象的容器
* @return {G.shape} 返回一个绘制的图形作为keyShape, 通过combo.get('keyShape'),可以获取
*/
drawShape(cfg, group){},
/**
* 绘制后的附加操作,默认没有任何操作
* @param {Object} cfg Combo 的配置项
* @param {G.Group} group 图形分组,Combo 中的图形对象的容器
*/
afterDraw(cfg, group) {},
/**
* 更新节点后的操作,新增的图形需要在这里控制其更新逻辑
* @override
* @param {Object} cfg 节点的配置项
* @param {Combo} combo 节点
*/
afterUpdate(cfg, combo) {},
/**
* 响应 Combo 的状态变化。
* 在需要使用动画来响应状态变化时需要被复写,其他样式的响应参见下文提及的 [配置状态样式] 文档
* @param {String} name 状态名称
* @param {Object} value 状态值
* @param {Combo} combo 节点
*/
setState(name, value, combo) {},
},
// 被继承的 Combo 类型名,可选:'circle' 或 'rect'
'circle',
)
注意事项https://g6.antv.antgroup.com/manual/middle/elements/combos/custom-combo#注意事项必读
- 在drawShape中不需要添加label图形,父类方法自动添加label,可以通过配置方式指定label的位置和样式。
- 与自定义节点边不同,不建议复写,update和draw方法,否则会使用combo根据子元素更新的逻辑异常。
- 复写drawShpae方法的返回值推荐与继承内置的circle/rect的keyShape一致。即继承circle时返回 一个cirele图形,继承rect时,返回 一个rect图形。
- 除keyShape外,自定义新增的图形需要在afterUpdate中定义其位置更新逻辑。
内置 Rect Combo 位置逻辑详解
https://g6.antv.antgroup.com/manual/middle/elements/combos/custom-combo#内置-rect-combo-位置逻辑详解
- 下图灰色虚线框是子元素分布范围,高宽分别为innerHeight, innerWidth。
- 虚线框外面还有padding,该combo的keyShape的width和height分别是innerWidth + padding,innerHeight+padding。
- combo的内部图形是以自身坐标为参考系,虚线框的正中心为原点。
- 由于padding上下左右不对称,(X, Y)的坐标,不是简单的(-width/2, -height/2)。
- rect的combo的label是左上角,上边距为refX,左边距为refY。
drawShape: function drawShape(cfg, group) {
const self = this;
const style = self.getShapeStyle(cfg);
// style.width 对应的是combo的宽,即是keyShape的width,innerWidth + padding[1] + padding[3]
// style.height 对应的是combo的高,即是keyShape的height ,innerHeight+ padding[0] + padding[2]
// cfg.style.width 子元素分布的宽度innerWidth,这个不包含padding
// cfg.style.height 子元素分布的宽度innerHeight,这个不包含padding
}
路径PATH函数命令
大写是使用绝对定位,也就是说是坐标轴定位。小写是相对定位,从上一个位置开始。如m 10 10, 是从当前位置向上移动10个单位,向右移10个单位
M 移动画笔,不作画,如:M 10 10,将画笔移到坐标为(10,10)的位置
L 画线,如L 10 10,从当前位置到坐标为(10,10)的位置两点间画一条线段。
H 绘制水平线, H 10,从当前位置到X轴位置 10 间水平画一条线段。
V 绘制垂直线, V 10,从当前位置到Y轴位置 10 间垂直平画一条线段。
Z 从当前位置画一条线到路径的起始位置完成闭合。
C 三次贝塞尔曲线,需要三个坐标,第一个控制点,第二控制点,曲线点,如 C x1 y1, x2 y2, x y;
Q 二次贝塞尔曲线,需要二个坐标,第一个控制点,曲线点,如 C x1 y1, x y;
A 画弧线
问题
手动调用布局时在graph.read()后面监听afterrender事件不生效
https://github.com/antvis/G6/issues/2598
// 引入dagre布局
import { DagreLayout } from '@antv/layout/es/layout/dagre';
export function calcPositionDagre(options, data) {
const dagreLayout = new DagreLayout(options);
// 计算出坐标
dagreLayout.layout(data);
}
// 不生效
graph.read(data)
graph.on('afterrender', fn) // 不生效
// 改成这样才生效
graph.data(data)
graph.on('afterrender', fn) // 生效
graph.render()
修改坐标不生效
修改坐标后不生效,实际要调用graph.refreshPositions()才生效
修改边的sourceAnchor和targetAnchor时会影响边startPoint 和 endPoint 的位置
当计算坐标需要startPoint 和 endPoint 的位置,且需要更新sourceAnchor和targetAnchor时,只能先更新sourceAnchor和targetAnchor的位置。