通过G6实现自定义节点
因为原先用的可视化不支持自定义节点的操作所以在想用别的可视化来实现这个效果。之前有调研过G6也研究过它的源码,所以第一时间想到的就是G6。
G6的API用起来就挺舒服的,哈哈哈。
// 模拟数据 !!!注意属性里不能有type,会渲染不出来。原因是type是G6的保留字符.
const data = {
nodes: [{
id: 'node1',
dataType: 'REDCODE',
keyInfo: '男 / 22岁',
name: "Sing"
},
{
id: 'node2',
dataType: 'YELLOWCODE',
keyInfo: '男 / 22岁',
name: "Sing"
},
{
id: 'node3',
dataType: 'YELLOWCODE',
keyInfo: '男 / 22岁',
name: "Sing"
},
{
id: 'node4',
dataType: 'YELLOWCODE',
keyInfo: '男 / 22岁',
name: "Sing"
},
{
id: 'node5',
dataType: 'YELLOWCODE',
keyInfo: '男 / 22岁',
name: "Sing"
},
],
edges: [{
source: 'node1',
target: 'node2'
},
{
source: 'node1',
target: 'node3'
},
{
source: 'node1',
target: 'node4'
},
{
source: 'node1',
target: 'node5'
},
],
};
// 点配置
const CODES = {
REDCODE: "#F5222D",
YELLOWCODE: "#f7dc6f",
GREENCODE: "#41912b"
};
const getNodeConfig = (node) => {
return {
fontColor: "#000", // 文字颜色
bgColor: CODES[node.dataType] || "#41912b", // 背景颜色
mainColor: "#fff", // 信息内容的背景颜色
fontSize: 16, // 字体大小
}
}
// 基准绘制方法
const boxHeight = 80,
boxWidth = 180,
padding_Top = 10,
padding_Left = -10,
mainWidth = 90,
imageRect = 60;
const nodeBasicMethod = {
// 创建点位置
createNodeBox: (group, config, width, height) => {
// 父级容器
const container = group.addShape('rect', {
attr: {
x: 0,
y: 0,
width,
height
},
name: 'father-shape',
draggable: true,
});
// 主体
group.addShape('rect', {
attrs: {
x: -width / 2,
y: 0,
width,
height,
fill: config.bgColor,
stroke: config.bgColor,
radius: 10,
cursor: 'pointer',
},
name: 'main-shape',
draggable: true,
});
// 文字部分
group.addShape('rect', {
attrs: {
x: padding_Left,
y: padding_Top,
width: mainWidth,
height: boxHeight - padding_Top * 2,
fill: config.mainColor,
stroke: config.mainColor,
radius: 2,
cursor: 'pointer',
},
name: 'text-shape',
draggable: true,
});
return container;
},
// 做一些预处理,和初始化设置
setState: (name, value, item) => {
const group = item.getContainer();
},
afterDraw: (cfg, group) => {
group.on('click', (e) => {
console.log('you click: ' + cfg.id)
})
}
}
// 自定义节点样式
G6.registerNode('card-node', {
draw: (cfg, group) => {
const config = getNodeConfig(cfg);
const container = nodeBasicMethod.createNodeBox(group, config, boxWidth, boxHeight);
// 文字添加
group.addShape('text', {
attrs: {
text: cfg.name,
x: 0,
y: boxHeight / 2 - config.fontSize,
fontSize: config.fontSize,
textAlign: 'left',
textBaseline: 'middle',
fill: config.fontColor,
},
name: 'name-text-shape',
draggable: true,
});
group.addShape('text', {
attrs: {
text: cfg.keyInfo,
x: 0,
y: boxHeight / 2 + config.fontSize,
fontSize: config.fontSize,
textAlign: 'left',
textBaseline: 'middle',
fill: config.fontColor,
},
name: 'keyInfo-text-shape',
draggable: true,
});
// 头像
group.addShape('image', {
attrs: {
x: padding_Left - imageRect - 5,
y: boxHeight / 2 - imageRect / 2,
img: 'https://g.alicdn.com/cm-design/arms-trace/1.0.155/styles/armsTrace/images/TAIR.png',
width: imageRect,
height: imageRect
},
name: 'image-shape',
draggable: true,
});
return container
},
setState: nodeBasicMethod.setState,
afterDraw: nodeBasicMethod.afterDraw
})
// 生成G6实例,如果要使用树形布局使用 `new G6.TreeGraph` 的方式生成实例
const graph = new G6.Graph({
container: 'container',
width: 1200,
height: 800,
fitCenter: true,
fitView: true,
modes: {
default: ['zoom-canvas', 'drag-canvas', 'drag-node'],
},
layout: {
type: 'dagre',
nodeSize: [boxWidth, boxHeight],
nodesep: 60,
ranksep: 60,
},
// 节点样式修改
defaultNode: {
type: 'card-node',
},
// 边样式修改
defaultEdge: {
size: 1,
color: '#e2e2e2',
style: {
endArrow: {
path: 'M 0,0 L 8,4 L 8,-4 Z',
fill: '#e2e2e2',
},
},
}
});
graph.data(data);
graph.render();