本文主要是介绍AntV G6自定义流程图Graph,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
AntV G6自定义流程图Graph
- AntV G6自定义流程图Graph
- 一、先看下我的效果图
- 二、参考官方图表示例地址
- 三、代码已整合成vue组件
- 四、这里提供了直接改官方示例数据,简单的参考
AntV G6自定义流程图Graph
前言:自定义流程图节点样式、节点可拖动,节点文字过长省略,文字过长的节点悬浮展示tooltip插件悬浮框,修改tooltip悬浮框样式。
一、先看下我的效果图
二、参考官方图表示例地址
Dagre 流程图
三、代码已整合成vue组件
调用组件传值给mapData,这里只是自己演示设置了假数据a
<template><div style="width: 100%;height: 100%;"><!-- 流程预览图画布 --><div id="containerBox"style="background: #F7F8FA;border-radius: 4px;"></div></div>
</template>
<script>
import G6 from '@antv/g6'
import insertCss from 'insert-css';
// 这个样式是作用于modes里的tooltip
insertCss(`.g6-tooltip {border-radius: 4px;font-size: 12px;color: #fff;background-color: #3C3D42;text-align: left;width: 240px;padding: 6px 12px;}
`);
insertCss(`.g6-component-tooltip {border-radius: 4px;font-size: 12px;color: #fff;background-color: #3C3D42;text-align: left;width: 240px;padding: 6px 12px;}
`);
export default {name: "previewProcess",data () {return {a: {nodes: [{id: '1',dataType: 'start',name: 'alps_file1',},{id: '2',dataType: 'condition',name: 'alps_file2二二二二二二二二二二二二二二二二二二二二二二二二二二二二二二二二二二二二二二二二二',},{id: '3',dataType: 'examine',name: 'alps_file3三三三三三三三三三三三三三三三三三三三三三三三三三三三三三三三三三三三三三三三三三',},{id: '4',dataType: 'examine',name: 'sql_file4四四四四四四四四四四四四四四四四四四四四四四四四四四四四四四四四四四四四四四四四四四',},{id: '5',dataType: 'examine',name: 'sql_file5',},{id: '6',dataType: 'end',name: 'feature_etl_1',}],edges: [{source: '1',target: '2',},{source: '1',target: '3',},{source: '2',target: '4',},{source: '3',target: '4',},{source: '4',target: '5',},{source: '5',target: '6',}],}}},props: {mapData: { // 预览数据type: Object,default: () => {return {}}},mapHeight: { // 高度Htype: String,default: '600'},},mounted () {this.customNode()this.createNode(this.a) // 参数名为a,后期正式使用a都改成mapData},activated () {},watch: {},computed: {},methods: {// 文字过长显示...fittingString (str, maxWidth, fontSize) {const ellipsis = '...'const ellipsisLength = G6.Util.getTextSize(ellipsis, fontSize)[0]let currentWidth = 0let res = strconst pattern = new RegExp('[\u4E00-\u9FA5]+') // distinguish the Chinese charactors and lettersstr.split('').forEach((letter, i) => {if (currentWidth > maxWidth - ellipsisLength) returnif (pattern.test(letter)) {// Chinese charactorscurrentWidth += fontSize} else {// get the width of single letter according to the fontSizecurrentWidth += G6.Util.getLetterWidth(letter, fontSize)}if (currentWidth > maxWidth - ellipsisLength) {res = `${str.substr(0, i)}${ellipsis}`}})return res},// 自定义节点方法customNode () {const _that = thisG6.registerNode('sql',{drawShape (cfg, group) {let index = _that.a.nodes.length - 1// 判断为开始、结束节点if (cfg.id === _that.a.nodes[0].id || cfg.id === _that.a.nodes[index].id) {const startEnd = group.addShape('rect', {attrs: {x: -10,y: -25,width: 100,height: 36,stroke: '#C3C5D9',radius: 18,fill: '#fff',},name: 'main-box',draggable: true,});group.addShape('text', {attrs: {text: cfg.id === _that.a.nodes[0].id ? '发起节点' : '结束',x: 40,y: -6,textAlign: 'center',textBaseline: 'middle',fill: '#202340',fontSize: 14,fontWeight: 500,fontFamily: 'PingFangSC-Regular, PingFang SC',lineHeight: 20,},name: 'text-shape',});return startEnd;} else {// 判断是条件还是审核人展示不同样式if (cfg.dataType === 'condition') {// 条件:整个节点矩形const rect = group.addShape('rect', {attrs: {x: -75,y: -25,width: 230,height: 86,radius: 4,stroke: '#C3C5D9',fill: '#F7F8FA',lineWidth: 1,},name: 'rect-shape',});// 条件:上面标题矩形const titleRect = group.addShape('rect', {attrs: {x: -74.5,y: -24.5,width: 229,height: 35,radius: [4, 4, 0, 0],stroke: '#C3C5D9',fill: '#E2E3EE',lineWidth: 0,},name: 'rect-title',});// 条件:上面矩形标题文字const title = group.addShape('text', {attrs: {text: _that.fittingString(cfg.dataType + '标题', 198, 14),x: -58,y: -8,textAlign: 'left',textBaseline: 'middle',fill: '#565B85',fontSize: 14,fontWeight: 500,fontFamily: 'PingFangSC-Regular, PingFang SC',lineHeight: 20,},name: 'title-box',});// 条件:矩形下面的文本文字const text = group.addShape('text', {attrs: {text: _that.fittingString(cfg.name + '文本', 198, 14),x: -58,y: 35,textAlign: 'left',textBaseline: 'middle',fill: '#202340',fontSize: 14,fontWeight: 500,fontFamily: 'PingFangSC-Regular, PingFang SC',lineHeight: 20,},name: 'text-box',});return rect;} else { // 审核人展示的样式// 审核人:整个节点矩形const rect = group.addShape('rect', {attrs: {x: -75,y: -25,width: 230,height: 86,radius: 4,stroke: '#FFCA80',fill: '#FFF9F2',lineWidth: 1,},name: 'rect-shape',});// 审核人:上面标题矩形const titleRect = group.addShape('rect', {attrs: {x: -74.5,y: -24.5,width: 229,height: 35,radius: [4, 4, 0, 0],stroke: '#C3C5D9',fill: '#FFDFB2',lineWidth: 0,},name: 'rect-title',});// 审核人:上面矩形标题文字const title = group.addShape('text', {attrs: {text: _that.fittingString(cfg.dataType + '标题', 198, 14),x: -58,y: -8,textAlign: 'left',textBaseline: 'middle',fill: '#D97F00',fontSize: 14,fontWeight: 500,fontFamily: 'PingFangSC-Regular, PingFang SC',lineHeight: 20,},name: 'title-box',});// 审核人:矩形下面的文本文字const text = group.addShape('text', {attrs: {text: _that.fittingString(cfg.name + '文本', 198, 14),x: -58,y: 35,textAlign: 'left',textBaseline: 'middle',fill: '#202340',fontSize: 14,fontWeight: 500,fontFamily: 'PingFangSC-Regular, PingFang SC',lineHeight: 20,},name: 'text-box',});return rect;}}},},'single-node',);},// 根据数据创建树状图节点createNode (mapData) {let tooltip = new G6.Tooltip({offsetX: 0,offsetY: 30,// 固定tooltip位置// fixToNode: [0, 1],// 允许出现 tooltip 的 item 类型itemTypes: ['node'],// 自定义 tooltip 内容getContent: (e) => {console.log('e=======', e.item);const outDiv = document.createElement('div');outDiv.style.width = '100%';// outDiv.style.background = 'red';outDiv.innerHTML = `<div>${e.item._cfg.model.name}</div>`;return outDiv;},shouldBegin: (e) => {let str = this.fittingString(e.item._cfg.model.name, 198, 14)let index = str.indexOf('.')if (index > -1) {return true}return false},});const container = document.getElementById('containerBox');const width = container.scrollWidth;const height = container.scrollHeight || this.mapHeight;const graph = new G6.Graph({container: 'containerBox',width,height,plugins: [tooltip],layout: {type: 'dagre',nodesepFunc: (d) => { // 节点左右边距if (d.id === '3') {return 500;}return 50;},ranksep: 60, // 节点上下边距},defaultNode: {type: 'sql',anchorPoints: [[0.5, 1],[0.5, 0]]},defaultEdge: { // 连接线样式type: 'polyline',style: {radius: 0,offset: 45,// 这个字段默认是true// endArrow: true,lineWidth: 2,stroke: '#C3C5D9',endArrow: {path: 'M 0,0 L 8,4 L 8,-4 Z',fill: '#C3C5D9',},},},nodeStateStyles: {selected: {stroke: '#d9d9d9',fill: '#5394ef',},},modes: {default: ['drag-canvas','zoom-canvas','drag-node',// {// type: 'tooltip',// formatText (model) {// const cfg = model.name;// return cfg// },// shouldBegin: (e) => {// let str = this.fittingString(e.item._cfg.model.name, 198, 14)// let index = str.indexOf('.')// if (index > -1) {// return true// }// return false// },// offset: 30// },],},fitView: true,});graph.data(mapData);graph.render();// 这里是用于判断连接线是否有箭头// mapData.nodes.forEach((node) => {// if (node.dataType === 'condition') {// mapData.edges.forEach((edge) => {// if (edge.target === node.id) {// edge.style.endArrow = false;// }// })// }// });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);};}}
}
</script>
四、这里提供了直接改官方示例数据,简单的参考
在官方图表示例找到Dagre 流程图
import G6 from '@antv/g6';
import insertCss from 'insert-css';insertCss(`.g6-tooltip {border-radius: 6px;font-size: 12px;color: #fff;background-color: #000;padding: 2px 8px;text-align: center;}
`);const data = {nodes: [{id: '1',dataType: 'alps',name: 'alps_file1',conf: [{label: 'conf',value: 'pai_graph.conf',},{label: 'dot',value: 'pai_graph.dot',},{label: 'init',value: 'init.rc',},],},{id: '2',dataType: 'alps',name: 'alps_file2',conf: [{label: 'conf',value: 'pai_graph.conf',},{label: 'dot',value: 'pai_graph.dot',},{label: 'init',value: 'init.rc',},],},{id: '3',dataType: 'alps',name: '11111',conf: [{label: 'conf',value: 'pai_graph.conf',},{label: 'dot',value: 'pai_graph.dot',},{label: 'init',value: 'init.rc',},],},{id: '4',dataType: 'sql',name: 'sql_file1',conf: [{label: 'conf',value: 'pai_graph.conf',},{label: 'dot',value: 'pai_graph.dot',},{label: 'init',value: 'init.rc',},],},{id: '5',dataType: 'sql',name: 'sql_file2',conf: [{label: 'conf',value: 'pai_graph.conf',},{label: 'dot',value: 'pai_graph.dot',},{label: 'init',value: 'init.rc',},],},{id: '6',dataType: 'feature_etl',name: 'feature_etl_1',conf: [{label: 'conf',value: 'pai_graph.conf',},{label: 'dot',value: 'pai_graph.dot',},{label: 'init',value: 'init.rc',},],}],edges: [{source: '1',target: '2',},{source: '1',target: '3',},{source: '2',target: '4',},{source: '3',target: '4',},{source: '4',target: '5',},{source: '5',target: '6',}],
};G6.registerNode('sql',{drawShape(cfg, group) {const rect = group.addShape('rect', {attrs: {x: -75,y: -25,width: 150,height: 50,radius: 10,stroke: '#5B8FF9',fill: '#C6E5FF',lineWidth: 3,},name: 'rect-shape',});if (cfg.name) {group.addShape('text', {attrs: {text: cfg.name,x: 0,y: 0,fill: '#00287E',fontSize: 14,textAlign: 'center',textBaseline: 'middle',fontWeight: 'bold',},name: 'text-shape',});}return rect;},},'single-node',
);const container = document.getElementById('container');
const width = container.scrollWidth;
const height = container.scrollHeight || 500;
const graph = new G6.Graph({container: 'container',width,height,layout: {type: 'dagre',nodesepFunc: (d) => {if (d.id === '3') {return 500;}return 50;},ranksep: 70,},defaultNode: {type: 'sql',anchorPoints: [[0.5, 1],[0.5, 0]]},defaultEdge: {type: 'polyline',style: {radius: 0,offset: 45,endArrow: true,lineWidth: 2,stroke: '#C2C8D5',endArrow: {path: 'M 0,0 L 8,4 L 8,-4 Z',fill: '#C2C8D5',},},},nodeStateStyles: {selected: {stroke: '#d9d9d9',fill: '#5394ef',},},modes: {default: ['drag-canvas','zoom-canvas','drag-node',// 'click-select',// {// type: 'tooltip',// formatText(model) {// const cfg = model.conf;// const text = [];// cfg.forEach((row) => {// text.push(row.label + ':' + row.value + '<br>');// });// return text.join('\n');// },// offset: 30,// },],},fitView: true,
});
graph.data(data);
graph.render();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);};
这篇关于AntV G6自定义流程图Graph的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!