前言
最近在开发关系图,拓扑图等应用,所以用到了Antv G6模块,遇到自定义节点的问题,这边整理一下碰到的问题以及解决方案。以及针对文档上面group的整理。
其实文档上面有对group这个参数做介绍,找起来比较麻烦。这边整理一下,以及对应的设置。 这边ts的类型自己定义,我这边就不定义ts类型了。
自定义节点
G6文档上面有说明,自定义节点的方法如下:
// 方法说明: registerNode(节点名称,配置项,继承的节点名称)
G6.registerNode('nodeName', options, extendedNodeName)
也就是说,可以扩展某个内置节点,或者从无到有绘制一个节点。
扩展节点
扩展一个节点的话,这边以扩展rect内置节点为例,添加一个describe属性,放到label标签下面,方法如下:
G6.registerNode('rect-desc', {
afterDraw(cfg, group) {
const shape = group.get('children')[1]
shape.attr({
x: 0,
y: -10,
})
if (cfg.describe) {
return group.addShape('text', {
attrs: {
x: 0,
y: 10,
textAlign: 'center',
textBaseline: 'middle',
text: cfg.describe,
fill: '#000',
},
name: 'desc-shape',
draggable: true,
})
}
}
}, 'rect')
这边有很多个问题,我为什么不直接使用draw方法来创建,因为使用draw直接重写了rect的draw方法,一些rect基本的属性都会失效,包括锚点,路径等。 afterDraw 是在rect绘制之后进行添加,这边就使用了afterDraw方法来实现这个逻辑。
使用group.get获取元素,并针对该元素进行对应的修改。文章后有介绍。
这边使用了group.addShape这个方法来进行新增一个shape, 方法在文档中有进行介绍。
8.20更新,update扩展节点问题
因自定义节点可能会涉及到更新问题,所以自定义节点的时候,需要加上update属性,直接使用上面的方法,新增update方法。
G6.registerNode('rect-desc', {
afterDraw(cfg, group) {
// 绘制之后重写部分方法
const shape = group.get('children')[1]
shape.attr({
x: 0,
y: -10,
})
if (cfg.describe) {
return group.addShape('text', {
attrs: {
x: 0,
y: 10,
textAlign: 'center',
textBaseline: 'middle',
text: cfg.describe,
fill: '#000',
},
name: 'desc-shape',
draggable: true,
})
}
},
update(cfg, node) {
// 当节点更新时,重新修改当前组件的内容
const group = node.getContainer()
const shape = group.get('children')[1]
shape.attr({
x: 0,
y: -25
})
if (cfg.describe !== undefined) {
const child = group.find((ele) => ele.get('name') === 'desc-shape') // 因为新增的描述属性,这边更新的话需要先删除再新增。
group.removeChild(child)
return group.addShape('text', {
attrs: {
x: 0,
y: 10,
textAlign: 'center',
textBaseline: 'middle',
text: cfg.describe,
fill: '#000',
},
name: 'desc-shape',
draggable: true,
})
}
}
}, 'rect')
然后使用updateItem方法,来更新当前节点,如:
const node = {
describe: 'test test',
label: '测试'
}
graph.updateItem('node', node)
从无到有绘制一个节点
从无到有就引用官方的一个实例,新增一个节点,包括锚点、路径等内容都需要重新自己配置。
G6.registerNode('diamond', {
draw(cfg, group) {
// 如果 cfg 中定义了 style 需要同这里的属性进行融合
const keyShape = group.addShape('path', {
attrs: {
path: this.getPath(cfg), // 根据配置获取路径
stroke: cfg.color, // 颜色应用到描边上,如果应用到填充,则使用 fill: cfg.color
},
// must be assigned in G6 3.3 and later versions. it can be any value you want
name: 'path-shape',
// 设置 draggable 以允许响应鼠标的图拽事件
draggable: true,
});
if (cfg.label) {
// 如果有文本
// 如果需要复杂的文本配置项,可以通过 labeCfg 传入
// const style = (cfg.labelCfg && cfg.labelCfg.style) || {};
// style.text = cfg.label;
const label = group.addShape('text', {
// attrs: style
attrs: {
x: 0, // 居中
y: 0,
textAlign: 'center',
textBaseline: 'middle',
text: cfg.label,
fill: '#666',
},
// must be assigned in G6 3.3 and later versions. it can be any value you want
name: 'text-shape',
// 设置 draggable 以允许响应鼠标的图拽事件
draggable: true,
});
}
return keyShape;
},
// 返回菱形的路径
getPath(cfg) {
const size = cfg.size || [40, 40]; // 如果没有 size 时的默认大小
const width = size[0];
const height = size[1];
// / 1 \
// 4 2
// \ 3 /
const path = [
['M', 0, 0 - height / 2], // 上部顶点
['L', width / 2, 0], // 右侧顶点
['L', 0, height / 2], // 下部顶点
['L', -width / 2, 0], // 左侧顶点
['Z'], // 封闭
];
return path;
},
});
上面使用的是G6官方文档中绘制的节点,因为是新建节点,所以使用draw方法,来绘制一个新的节点。path 也就是路径,在getPah中有体现是怎么来绘制的。 总之,会创建一个图形分组,也就是group,对应节点中图形对象容器。
group方法介绍
文档中有各个方法介绍,这边只介绍几个在使用中遇到的问题,文档中group对象的介绍地址group对象介绍地址
- 修改对应节点
这边使用中有遇到获取group节点并进行修改位置的方法,也就是使用group.get方法
group.get('children')
此方法返回值在于在一个group中有几个子元素,比如rect。方法中返回了了两个元素,可以针对元素进行修改,如下:
const shape = group.get('children')[1]
shape.attr({
x: 0,
y: -10
})
元素修改和创建的shape方式相同,属性也相同。
graph 实例方法介绍
这边方法有很多,比如保存数据,以及导出数据等,这边晚点进行一一对方法进行收集和讲解。 这是G6提供的文档: graph实例方法
- 8.24 更新
- 修改元素状态
// 创建一个G6实例
const graph = new G6.Graph({
...
})
// graph 事件, 当前时间名称为边鼠标移入时
graph.on('edge:mouseenter', (evt) => {
const { item } = evt
// 设置边的状态active 为true
graph.setItemState(item, 'active', true)
})
// graph 事件, 当前时间名称为边鼠标移出时
graph.on('edge:mouseleave', (evt) => {
const { item } = evt
// 设置边的状态active 为true
graph.setItemState(item, 'active', false)
})