我正在参加「掘金·启航计划」
系列文章:
- 手摸手使用G6实现(轻)图编辑应用系列-初识G6
- 手摸手使用G6实现(轻)图编辑应用系列-自定义节点
- 手摸手使用G6实现(轻)图编辑应用系列-自定义边、箭头
- 手摸手使用G6实现(轻)图编辑应用系列-自定义行为
- 手摸手使用G6实现(轻)图编辑应用系列-后续优化
前言
上一节,自定义了节点,接下来通过自定义边、箭头来实现效果
边分析
- 整个拓扑中边涉及自环、直线、曲线
- 边样式以及文字样式
- 鼠标移入边,显示边背景的交互(由于上一节自定义节点没有涉及更新操作,通过此功能介绍一下)
- 鼠标移入节点,边样式也会有所变化
边实现
由于边的背景需要额外添加,所以需要继承内置边进行扩展自定义边;涉及自环、直线、曲线,需要自定义三个内置边,接下来拿直线作为例子
G6.registerEdge('customLine', {}, 'line',);
afterDraw 方法
- 实现思路
- 内置边默认边的关键图形name都为edge-shape
- 得到关键图形的shape,进而获取其样式属性
- 使用关键图形的样式属性作为 path 的属性,加一个层级低的shape
- 代码实现
afterDraw(cfg, group){
const keyShape = group.find(item => item.get('name') === 'edge-shape');
const style = keyShape.attr();
const path = group.addShape('path',{
attrs:{
...style,
lineWidth: 10,
stroke: '#a23ade',
opacity: 0.8,
endArrow: false,
startArrow: false
},
zIndex: -1,
name: 'edge-bk-shape'
})
path.hide();
group.sort();
};
afterUpdate 方法
- 实现思路
- 由于拖动节点时,会触发update方法,边的path会变化,需要同步处理边背景保持同步变化,否则边背景一直都在初始化时边的位置
- 代码实现
afterUpdate(cfg, node){
const group = node.getContainer();
const keyShape = group.find(item => item.get('name') === 'edge-shape');
const edgeBk = group.find(item => item.get('name') === 'edge-bk-shape');
edgeBk.attr('path', keyShape.attr('path'));
};
setState 方法
-
实现思路
- 通过graph.setItemState给边设置不同状态值,针对状态值做出相应效果
- 大概就是通过获取图形分组,根据设置的图形name找到指定图形,改变属性值
-
代码实现
setState = (name, value, item) => {
const group = item.getContainer();
if(name === 'activeEdge'){
const shape = group.find(child=> child.get('name') === 'edge-bk-shape')
if(value){
shape.show();
}else{
shape.hide();
}
}
if (name === 'active') {
const shape = group.find(child=> child.get('name') === 'edge-shape')
if (value) {
shape.attr(Object.assign(this.getArrowStyle(edgeModel, value), styleObj.activeLine));
} else {
shape.attr(Object.assign(this.getArrowStyle(edgeModel, value), styleObj.inactiveLine));
}
};
边以及文字样式
- 通过默认边配置列举常用样式配置
defaultEdge: {
type: 'customLine',
style: {
// 边箭头
startArrow: false,
endArrow: true,
// 边样式
stroke: '#A3A5A9',
lineWidth: 1,
cursor: 'pointer',
lineDash: undefined,
},
// 边上文本配置
labelCfg: {
// autoRotate: true, // 文本根据边方向旋转
style:{
// textAlign: 'center',
// textBaseline: 'center',
fill: '#606266',
fontSize: 10,
fontWeight: 300,
fontFamily: '',
cursor: 'pointer',
background: {
//文字背景
fill: '#FFFFFF',
stroke: '#E6E8EC',
padding: [4, 2, 2, 2],
},
}
},
},
箭头分析
箭头样式与默认G6箭头不同,需要自定义实现
箭头实现
- G6内有默认箭头、内置箭头、自定义箭头
- 默认箭头
- 内置箭头
- 官方封装的工具方法,支持宽度、长度、偏移量入参,最终转换为path路径
- 自定义箭头
- 通过 path 进行绘制箭头路径
- 绘制箭头的坐标系和自定义节点时的坐标一致
- 例子
defaultEdge: { style: { endArrow: { // 自定义箭头指向(0, 0),尾部朝向 x 轴正方向的 path path: 'M 0,0 L 20,10 L 20,-10 Z', // 箭头的偏移量,正值代表向 x 轴负方向移动,如下图 // d: 10, }, }, },
- 代码实现
defaultEdge: {
style: {
// 边箭头
startArrow: false,
endArrow: {
/// 使用内置箭头实现
path: G6.Arrow.vee(6, 10, 0),
d: 0
}
},
},
结尾
截至到此,自定义边、箭头实现完成,下一节会介绍实现自定义行为的步骤
希望看完的朋友可以点个喜欢/关注,您的支持是对我最大的鼓励