概述
本文档主要向大家介绍如何拓展 G6 的边( Edge
),如有描述不清楚、有误的地方欢迎大家在 GitHub 上提 Issue 指正,或是直接 PR 修缮。根据您的贡献度,我们会视情况将您加入 AntV 共建者名录 :-)
提示 : 在使用自定义图项之前,应尽量熟练掌握绘图引擎 G 的使用。
注册 — registerEdge
我们通过以下接口往 G6 全局注册边:
// 注册边
G6.registerEdge(name, {
// 绘制
draw(item) {
return keyShape
},
// 获取路径
getPath(item) {
return path; // svg 规范 path 路径
},
// 起始箭头
startArrow: {
// 路径
path(item) {},
// 线缩短偏移
shorten(item) {},
// 样式
style(item) {}
},
// 结束箭头
endArrow: {
// 路径
path(item) {},
// 线缩短偏移
shorten(item) {},
// 样式
style(item) {}
}
}, extendShape);
绘制 — draw
跟节点一样,边的 draw
也是自定边图形的最小接口,决定了边最终画成什么样。 为了性能、箭头绘制成本等种种考虑,边的绘制不是绝对自由的。有以下几个规范的限制:
必须
keyShape
(既draw
方法返回的图形) 必须是G.Path
图形。必须 使用
getPath
方法获取keyShape
的路径。推荐 根据
item.getPoints()
获取边的路径。
例如:
G6.registerEdge('line', {
draw(item) {
const group = item.getGraphicGroup();
const path = this.getPath(item);
return group.addShape('path', {
attrs: {
path,
stroke: 'red'
}
});
},
getPath(item) {
const points = item.getPoints();
return Util.pointsToPolygon(points);
}
});
获得路径 — getPath
getPath()
是用于获取边路径的方法。在自定义边的时候,既可以像上面那样,复写 draw()
和 getPath()
也可以只复写 getPath()
,如果采用后者方法的好处是,你可以复用一些 G6 内部的实现,如 color,label,size 等,如下:
G6.registerEdge('horizontal-smooth', {
getPath(item) {
var points = item.getPoints();
var start = points[0];
var end = points[points.length - 1];
var hgap = Math.abs(end.x - start.x);
if (end.x > start.x) {
return [['M', start.x, start.y], ['C', start.x + hgap / 4, start.y, end.x - hgap / 2, end.y, end.x, end.y]];
}
return [['M', start.x, start.y], ['C', start.x - hgap / 4, start.y, end.x + hgap / 2, end.y, end.x, end.y]];
}
});
const data = {
nodes: [{
id: 'node1',
x: 100,
y: 200
},{
id: 'node2',
x: 300,
y: 260
}],
edges: [{
shape: 'horizontal-smooth',
target: 'node2',
source: 'node1'
}]
};
const graph = new G6.Graph({
container: 'mountNode',
width: 500,
height: 500
});
graph.edge({
label(model) {
return model.shape;
},
color: 'red',
size: 2
});
graph.read(data);
箭头 — arrow
箭头虽然是个小东西,但实现它却是一个非常细致,且有一定复杂度的活儿。如果你稍微不注意,可能就会画出下面这样的东西:
露点
戳进去
绘制一个完美的箭头并不是件容易的事,详见:聊个 5 毛钱箭头 。为了降低自定义箭头的复杂度,G6 有自己的一套定义箭头的机制,如果您需要自定义一个箭头,你最多需要以下三个步骤:
第一步:设置箭头的形状 path [必选]
首先,我们要构建一个以自身坐标系原点,为箭头端点的,箭头 path 路径。
第二步:设置边的端点偏移 shorten [可选]
第三步:设置箭头的通用样式 style [可选]
示例:
这个示例给出了根据 AntV 箭头的设计稿,基于 G6 箭头机制的具体实现:
G6.registerEdge('customEdge', {
endArrow: {
path(item) {
const keyShape = item.getKeyShape();
let lineWidth = keyShape.attr('lineWidth');
lineWidth = lineWidth > MIN_ARROW_SIZE ? lineWidth : MIN_ARROW_SIZE;
const width = lineWidth * 10 / 3;
const halfHeight = lineWidth * 4 / 3;
const radius = lineWidth * 4;
return [
[ 'M', -width, halfHeight ],
[ 'L', 0, 0 ],
[ 'L', -width, -halfHeight ],
[ 'A', radius, radius, 0, 0, 1, -width, halfHeight ],
[ 'Z' ]
];
},
shorten(item) {
const keyShape = item.getKeyShape();
const lineWidth = keyShape.attr('lineWidth');
return (lineWidth > MIN_ARROW_SIZE ? lineWidth : MIN_ARROW_SIZE) * 3.1;
},
style(item) {
const keyShape = item.getKeyShape();
const { strokeOpacity, stroke } = keyShape.attr();
return {
fillOpacity: strokeOpacity,
fill: stroke
};
}
}
});