需求描述
需要实现类似下图中的G6力导向图:节点填充圆形图片,且需要描边
实现思路
思路一
参考G6圆形内置节点,可实现在带有描边的圆形节点上添加图片效果,但图片不支持裁剪(如果是方形图片会盖住圆形节点的描边);
思路二
参考G6图片内置节点(要观察裁剪效果,需将在线示例中的配置项defaultNode.clipCfg.show改为true),可实现裁剪图片效果,但该类型节点不支持添加描边;
最终思路
使用自定义节点:
- 首先尝试使用自定义DOM节点实现,优点是实现节点样式非常自由,缺点是后续修改节点都要直接操作DOM,适用于需要实现特殊展示效果、偏重展示的场景;
- 笔者的应用场景需要支持较多交互操作,因此最终实现思路是将头像框拆成三个图层:带描边的圆形节点、裁剪为圆形的图片节点、底部文字节点,可将以下参考代码拷贝到文末的官网示例中调试运行~
参考代码
import G6 from '@antv/g6';
/**
* 注册自定义节点
*/
G6.registerNode(
'avatar',
{
draw: (cfg, group) => {
const nodeSize = cfg.size
let offset = -nodeSize / 2 // 节点偏移量,-节点尺寸/2
let nodeRadius = nodeSize / 2
// 带描边的圆形节点
group.addShape('circle', {
draggable: true,
attrs: {
x: 0,
y: 0,
r: nodeRadius,
stroke: '#9fc8fe', // 描边
lineWidth: 2 // 描边宽度
},
});
// 图片节点,需调用setClip实现裁剪
const shape = group.addShape('image', {
draggable: true,
attrs: {
x: offset,
y: offset,
width: nodeSize,
height: nodeSize,
img: cfg.img
},
zIndex: 2,
});
// 裁剪图片,支持 circle、rect、ellipse、Polygon 及自定义 path clip
shape.setClip({
type: 'circle',
attrs: {
r: nodeSize / 2 - 1,
x: 0,
y: 0,
},
})
// 文字节点(文字居中:x-0,textAlign-center;显示在节点下方:y-节点高度)
group.addShape('text', {
attrs: {
x: 0,
y: nodeSize,
width: nodeSize,
height: cfg.fontHeight,
lineHeight: cfg.fontHeight,
textAlign: `center`,
fontSize: 24,
text: cfg.label,
fill: '#555',
stroke: 'red'
},
zIndex: 1, // 排到最底层
});
return shape;
}
},
'circle'
);
/** 数据 */
const data = {
nodes: [
{
id: 'node1',
x: 10,
y: 100,
label: '节点A',
img: "https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*ch6rTrCxb6YAAAAAAAAAAABkARQnAQ",
},
{
id: 'node2',
x: 200,
y: 100,
label: '节点B',
img: "https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*95GYRI0zPx8AAAAAAAAAAABkARQnAQ",
},
],
edges: [
{
source: 'node1',
target: 'node2',
style: {
// endArrow: true,
lineWidth: 1, // 线宽
stroke: '#BCBCBC', // 线的颜色
endArrow: { // 设置终点箭头
// 使用内置箭头路径函数,参数为箭头的 宽度、长度、偏移量(默认为 0,与 d 对应)
path: G6.Arrow.triangle(18, 24, 26),
d: 12,
fill: '#6d81d2' // 箭头填充为实体有颜色
}
},
},
],
};
const container = document.getElementById('container');
const width = container.scrollWidth;
const height = (container.scrollHeight || 500) - 100;
const descriptionDiv = document.createElement('div');
descriptionDiv.innerHTML = `实现带描边的圆形图片(头像框)节点效果~`;
container.appendChild(descriptionDiv);
const graph = new G6.Graph({
container: 'container',
width,
height,
// renderer: 'svg', // 渲染模式默认为canvas,如果使用svg模式,边的箭头显示会有问题
linkCenter: true, // 设置边连入节点的中心(箭头指向节点中心)
layout: {
type: 'force', // force力导布局
linkDistance: 200, // 指定边距离
},
defaultNode: { // 节点通用配置
type: 'avatar',
size: 80,
fontHeight: 20
},
defaultEdge: { // 边通用配置
type: 'quadratic', // 指定边的形状为二阶贝塞尔曲线
size: 1,
}
});
graph.data(data);
graph.render();
在线运行
可以拷贝到以下官网示例,在线运行调试:
G6自定义节点-DOM节点
参考网址
[1] G6圆形内置节点
[2] G6图片内置节点
[3] G6自定义节点-DOM节点