edges连接线采用 type=‘polyline’ 折线
style: {
radius: 20, // 折点圆角
offset: 20, // 起始最近拐点距离
controlPoints: [
{ x: 20, y: 20 }, // 按照坐标点 第一个拐点位置
{ x: 40, y: 40 }, // 第二个拐点位置
]
},
/**
* @params g6data {nodes: [], edges: []}
* @params heightBox canva容器的高度
*/
renderG6Canvas = (g6data, heightBox) => {
if (!g6data.nodes.length) {
this.currentGraph && this.currentGraph.destroy();
return;
}
const container = document.getElementById('container');
const width = container.scrollWidth;
const height = heightBox || 500;
// 提前声明卡片搭配的颜色 - 渐变色
const bgColor = {
success: 'l(180) 0:#FFFFFF 1:#E2FAEE', // 已完成
processFailed: 'l(180) 0:#FFFFFF 1:#FFEBEB', // 流程失败
processException: 'l(180) 0:#FFFFFF 1:#FFF1D5', // 流程异常
haveInHand: 'l(180) 0:#FFFFFF 1:#EBF3FF', // 进行中
notStarted: 'l(180) 0:#FFFFFF 1:#F0F2F5' // 未开始
};
const tipBgColor = {
success: '#E8F9E8', // 已完成
processFailed: '#FAE7E7', // 流程失败
processException: '#FFECE4', // 流程异常
haveInHand: '#EBF3FF', // 进行中
notStarted: '#F0F2F5' // 未开始
};
const tipTextColor = {
success: '#1DC11D', // 已完成
processFailed: '#F23C3C', // 流程失败
processException: '#FF9419', // 流程异常
haveInHand: '#3386F1', // 进行中
notStarted: '#333333' // 未开始
};
G6.registerNode(
'card-node',
{
drawShape: function drawShape(cfg, group) {
// console.log(cfg, 'cfg');
// cfg 为 nodes 中的每一组数据
const r = 2;
let textColor = '#fff';
let textBgColor = 'green';
let titleBgColor = 'l(180) 0:#FFFFFF 1:#E2FAEE';
let statusTip = '已完成';
let contentLength;
switch (cfg.status) {
// 已完成
case 'DONE':
textColor = tipTextColor.success;
textBgColor = tipBgColor.success;
titleBgColor = bgColor.success;
statusTip = '已完成';
break;
case 'SKIP':
textColor = tipTextColor.success;
textBgColor = tipBgColor.success;
titleBgColor = bgColor.success;
statusTip = '已完成';
break;
// 进行中
case 'RUNNING':
textColor = tipTextColor.haveInHand;
textBgColor = tipBgColor.haveInHand;
titleBgColor = bgColor.haveInHand;
statusTip = '进行中';
break;
// 未开始
case 'EXIST':
textColor = tipTextColor.notStarted;
textBgColor = tipBgColor.notStarted;
titleBgColor = bgColor.notStarted;
statusTip = '未开始';
break;
// 流程异常
case 'STOP':
textColor = tipTextColor.processException;
textBgColor = tipBgColor.processException;
titleBgColor = bgColor.processException;
statusTip = '流程异常';
break;
// 失败
case 'ERROR':
textColor = tipTextColor.processFailed;
textBgColor = tipBgColor.processFailed;
titleBgColor = bgColor.processFailed;
statusTip = '流程失败';
break;
}
if (cfg.key) { // 可以通过if else 判断什么数据展示什么形状和内容
// 左侧
const shape = group.addShape('rect', {
attrs: {
x: 0,
y: 0,
width: 28,
height: cfg.height,
fill: '#ddd',
radius: 20
},
name: 'left-box',
draggable: true
});
// 左侧内容 -- 垂直居中的文字可以使用循环
for (let i = 0; i < cfg.name.length; i++) {
group.addShape('text', {
attrs: {
textBaseline: 'top',
x: 7,
y: parseInt(cfg.height / 2) + 20 * i,
text: cfg.name[i],
fill: 'rgba(17,17,17,1)',
fontSize: 14
},
name: 'left-title'
});
}
// 总耗时
group.addShape('text', {
attrs: {
textBaseline: 'top',
y: 10,
x: 90,
text: `总耗时`,
fill: 'rgba(17,17,17,1)',
fontSize: 14,
textAlign: 'center'
},
name: 'timetext'
});
group.addShape('text', {
attrs: {
textBaseline: 'top',
y: 10,
x: 160,
text: `${cfg.timeReduce}`,
fill: 'rgba(89,104,245,1)',
fontSize: 14,
textAlign: 'center'
},
name: 'timeboxms'
});
return shape;
} else {
const shape = group.addShape('rect', {
attrs: {
x: 0,
y: 0,
width: 298,
height: cfg.height,
stroke: '#bbb',
fill: '#fff',
radius: r
},
name: 'main-box',
draggable: true
});
group.addShape('rect', {
attrs: {
x: 0,
y: 0,
width: 298,
height: 37,
fill: titleBgColor,
radius: [r, r, 0, 0]
},
name: 'title-box',
draggable: true
});
// 标题title
group.addShape('text', {
attrs: {
textBaseline: 'top',
y: 9,
x: 16,
text: cfg.name,
fill: 'rgba(17,17,17,1)',
fontSize: 16
},
name: 'title'
});
let textHeight = 46;
for (let i = 0; i < cfg.newFeatures.length; i++) {
group.addShape('text', {
attrs: {
textBaseline: 'top',
y: textHeight + 24 * i,
x: 16,
text: cfg.newFeatures[i],
fill: 'rgba(51,51,51,1)',
fontSize: 14
},
name: `detail-text-${i}`
});
}
// hover展示详细内容
if (cfg.extraList.length) {
group.addShape('image', {
attrs: {
x: 265,
y: cfg.height - 20,
width: 14,
height: 14,
cursor: 'pointer',
img: 'https://img.alicdn.com/tfs/TB10g0l37T2gK0jSZFkXXcIQFXa-12-12.svg'
},
name: 'hover-icon'
});
}
// 状态背景盒子
group.addShape('rect', {
attrs: {
x: 232,
y: 9,
width: 50,
height: 20,
fill: textBgColor,
radius: 5
},
name: 'status-box-right',
draggable: true
});
// 状态
group.addShape('text', {
attrs: {
textBaseline: 'top',
y: 13,
x: 239,
lineHeight: 20,
text: statusTip,
fill: textColor,
fontSize: 12
},
name: `status-text`
});
return shape;
}
}
},
'single-node'
);
// g6 的触摸提示框插件
const tooltip = new G6.Tooltip({
getContent(e) {
const data = e?.item?._cfg?.model || {}; // nodes 中的数据
if (data.extraList.length) {
let res =
"<div style='width: 348px;word-wrap:break-word;word-break:break-all;font-size: 14px;text-align: left;line-height: 21px;padding: 10px'><ul>";
data.extraList.forEach((item) => {
res += `<li>${item}</li>`;
});
res += '</ul></div>';
return res;
}
return '';
},
offsetX: -250, // 提示框位置,如遇到位置展示不正确,设置canvas容器css position: 'relative'
offsetY: -250,
itemTypes: ['node'], // 触摸node展示tooltip
shouldBegin: (evt) => evt?.target?.cfg?.name === 'hover-icon' // 触摸卡片节点名字相同展示tooltip
});
const graph = new G6.Graph({
container: 'container',
width,
height,
fitCenter: false, // edges 水平垂直居中
fitView: true,
modes: {
default: ['drag-canvas', 'drag-node'] // 'drag-node' 拖拽节点
},
plugins: [tooltip], // 配置tooltip插件后,上面的才生效
defaultNode: {
type: 'card-node'
},
defaultEdge: {
type: 'line',
style: {
startArrow: {
path: G6.Arrow.triangle(9, 9), // 三角形
fill: '#DCDFE6' // 填充色
},
lineWidth: 1
}
}
});
// console.log(g6data, 'g6data');
if (this.currentGraph) {
this.currentGraph.destroy(); // 销毁画布
}
graph.data(g6data);
graph.render();
this.currentGraph = graph;
if (typeof window !== 'undefined')
window.onresize = () => {
if (!graph || graph.get('destroyed')) return;
if (!container || !container.scrollWidth || !container.scrollHeight)
return;
graph.changeSize(container.scrollWidth, container.scrollHeight);
};
};