美文网首页程序员
在vue项目中使用AntV X6构建流程图

在vue项目中使用AntV X6构建流程图

作者: 八月方便面 | 来源:发表于2022-06-24 09:55 被阅读0次

绘制的流程页面如下:

一、先在页面绘制两个div,放置左侧模型栏与右侧画布

<template>

    <div >

        <div class="content">

            <div class="app-stencil" ref="stencilContainer">

            </div>

            <div class="app-content" id="flowContainer" ref="container">

        </div>

    </div>

    </div>

</template>

二、js代码

1、引入X6

import {Graph, Shape, Addon, FunctionExt} from '@antv/x6';

const {Stencil} = Addon

const {Rect} = Shape

2、初始化画布

this.graph = new Graph({}) //配置可参考官网

3、左侧模型栏

const stencil = new Stencil({}) //配置可参考官网

4、节点链接桩的配置

data() {

//先在data里面定义,在绘制的时候直接使用

ports : {

                groups: {

                    top: {

                    position: 'top',

                    attrs: {

                        circle: {

                        r: 4,

                        magnet: true,

                        stroke: '#5F95FF',

                        strokeWidth: 1,

                        fill: '#fff',

                        style: {

                            visibility: 'hidden',

                        },

                        },

                    },

                    },

                    right: {

                    position: 'right',

                    attrs: {

                        circle: {

                        r: 4,

                        magnet: true,

                        stroke: '#5F95FF',

                        strokeWidth: 1,

                        fill: '#fff',

                        style: {

                            visibility: 'hidden',

                        },

                        },

                    },

                    },

                    bottom: {

                    position: 'bottom',

                    attrs: {

                        circle: {

                        r: 4,

                        magnet: true,

                        stroke: '#5F95FF',

                        strokeWidth: 1,

                        fill: '#fff',

                        style: {

                            visibility: 'hidden',

                        },

                        },

                    },

                    },

                    left: {

                    position: 'left',

                    attrs: {

                        circle: {

                        r: 4,

                        magnet: true,

                        stroke: '#5F95FF',

                        strokeWidth: 1,

                        fill: '#fff',

                        style: {

                            visibility: 'hidden',

                        },

                        },

                    },

                    },

                },

                items: [

                    {

                    group: 'top',

                    },

                    {

                    group: 'right',

                    },

                    {

                    group: 'bottom',

                    },

                    {

                    group: 'left',

                    },

                ],

            },

}

5、绘制节点的两种方式:

(1)第一种

const u3 = new Rect({

                width: 80,

                height: 50,

                attrs: {

                    text: {text: '资产审核员', fill: 'end'},

                    body: {

                        stroke: '#1890FF',

                        fill: 'rgba(24, 144, 255, 0.1)',

                        rx: 2,

                        ry: 2,

                        strokeWidth: 1,

                    },

                    label: {

                        fontSize: 14,

                        fill: '#666',

                        fontWeight: 400,

                    }

                },

                ports: {

                   ...this.ports

                }

            })

(2)第二种

            Graph.registerNode(

                'custom-polygon',

                {

                    inherit: 'polygon',

                    width: 80,

                    height: 50,

                    attrs: {

                    body: {

                        strokeWidth: 1,

                        stroke: '#FFAC32',

                        fill: 'rgba(255, 172, 50, 0.1)',

                    },

                    text: {

                        fontSize: 14,

                        fill: '#666666',

                    },

                    },

                    ports: {

                    ...this.ports,

                    items: [

                        {

                            group: 'top',

                        },

                        {

                            group: 'bottom',

                        },

                        {

                            group: 'right',

                        },

                        {

                            group: 'left',

                        },

                    ],

                    },

                },

                true,

            )

            const a1 = this.graph.createNode({

                shape: 'custom-polygon',

                attrs: {

                    body: {

                        refPoints: '0,10 10,0 20,10 10,20',

                    },

                },

                label: '判断',

            })

6、流程数据转化

this.graph.toJSON().cells//获取流程图的数据

this.graph.fromJSON(this.cellsData)//将数据转为流程图需要的格式

7、常用事件

this.graph.on('node:mouseenter', ({ node }) => {})//节点-鼠标滑过

this.graph.on('node:mouseleave', ({node}) => {})//节点-鼠标离开

this.graph.on('edge:mouseenter', ({ edge }) => {})//边-鼠标滑过

this.graph.on('edge:mouseleave', ({ edge }) => {})//边-鼠标离开

this.graph.on('node:click', ({ node }) => {})//节点-点击

this.graph.on('node:added', ({ node }) => {})//节点-添加

this.graph.on('node:removed', ({ node })=> {})//节点-删除

this.graph.on('edge:added', ({ edge})=> {})//边-添加

this.graph.on('edge:removed', ({ edge})=> {})//边-删除

this.graph.on('edge:click', ({ edge }) => {})//边-点击

this.graph.getNodes()//获取所有节点

this.graph.getEdges()//获取所有边

this.graph.getCellById(id)//通过id获取边/节点

edge.setLabels(['通过'])//设置边的label属性

8、节点/边添加删除操作

this.graph.on('node:mouseenter', ({ node }) => {

                //节点-鼠标进入添加删除操作

                const ports = container.querySelectorAll(

                    '.x6-port-body'

                )

                this.showPorts(ports, true)

                node.addTools({

                    name: 'button-remove',

                    args: {

                        x: 0,

                        y: 0,

                        offset: { x: 10, y: 10 },

                    },

                })

            })

9、画布缩放

sizeExpend(){

            //放大

            this.graph.zoom(0.2)

        },

        sizeShrink(){

            //缩小

            this.graph.zoom(-0.2)

        },

        sizeInit(){

            //复原

            this.graph.centerContent()

            this.graph.zoom(0.2, {

                absolute:true,

                minScale: 1,

                maxScale: 5,

                scaleGrid: 0.5,

            })

        }

10、代码如下

    methods:{   

        init() {

            this.graph = new Graph({

                container: this.$refs.container,

                width: '100%',

                height: '100%',

                grid: {

                    size: 10,

                    visible: true,

                    type: 'doubleMesh',

                    args: [

                        {

                            color: '#f5f5f5',

                            thickness: 1

                        },

                        {

                            color: '#f8f8f8',

                            thickness: 1,

                            factor: 4

                        }

                    ]

                },

                snapline: {

                    enabled: true,

                    sharp: true,

                },

                mousewheel: {

                    enabled: true,

                    modifiers: ['ctrl', 'meta'],

                    minScale: 0.5,

                    maxScale: 2

                },

                // 画布调整

                selecting: {

                    enabled: true,

                    multiple: true,

                    rubberband: true,

                    movable: true,

                    showNodeSelectionBox: true

                },

                connecting: {

                    anchor: 'center',

                    connectionPoint: 'anchor',

                    allowBlank: false,

                    highlight: true,

                    snap: true,

                    createEdge() {

                        return new Shape.Edge({

                            attrs: {

                                line: {

                                    stroke: '#ccc',

                                    strokeWidth: 1,

                                    targetMarker: {

                                        name: 'classic',

                                        size: 8

                                    }

                                },

                            },

                            label: {

                                attrs: {

                                    label: {

                                        // text:'ok',

                                        fill: '#A2B1C3',

                                        fontSize: 12,

                                    },

                                },

                            },

                            router: {

                                name: 'manhattan'

                            },

                            zIndex: 0

                        })

                    },

                    validateConnection({

                                            sourceView,

                                            targetView,

                                            sourceMagnet,

                                            targetMagnet

                                        }) {

                        if (sourceView === targetView) {

                            return false

                        }

                        if (!sourceMagnet) {

                            return false

                        }

                        if (!targetMagnet) {

                            return false

                        }

                        return true

                    }

                },

                highlighting: {

                    magnetAvailable: {

                        name: 'stroke',

                        args: {

                            padding: 4,

                            attrs: {

                                strokeWidth: 4,

                                stroke: 'rgba(223,234,255)'

                            }

                        }

                    }

                },

                snapline: true,

                history: true,

                clipboard: {

                    enabled: true

                },

                keyboard: {

                    enabled: true

                },

                embedding: {

                    enabled: true,

                    findParent({node}) {

                        const bbox = node.getBBox()

                        return this.getNodes().filter((node) => {

                            // 只有 data.parent 为 true 的节点才是父节点

                            const data = node.getData()

                            if (data && data.parent) {

                                const targetBBox = node.getBBox()

                                return bbox.isIntersectWithRect(targetBBox)

                            }

                            return false

                        })

                    }

                }

            })

            // graph.isPannable() // 画布是否可以平移

            // graph.enablePanning() // 启用画布平移

            this.graph.centerContent()

            /******************************** 左侧模型栏 ****************************/

            const stencil = new Stencil({

                title: '组件',

                target: this.graph,

                search: false, // 搜索

                collapsable: false,

                stencilGraphWidth: 240,

                stencilGraphHeight: 250,

                groups: [

                    {

                        name: 'processLibrary',

                        title: '流程事件',

                    },

                    {

                        name: 'staffPool',

                        title: '流程操作',

                    },

                ],

            })

            this.$refs.stencilContainer.appendChild(stencil.container)

            const u3 = new Rect({

                width: 80,

                height: 50,

                attrs: {

                    text: {text: '资产审核员', fill: 'end'},

                    body: {

                        stroke: '#1890FF',

                        fill: 'rgba(24, 144, 255, 0.1)',

                        rx: 2,

                        ry: 2,

                        strokeWidth: 1,

                    },

                    label: {

                        fontSize: 14,

                        fill: '#666',

                        fontWeight: 400,

                    }

                },

                ports: {

                   ...this.ports

                }

            })

            const u4 = new Rect({

                width: 80,

                height: 50,

                attrs: {

                    text: {text: '审核员', fill: 'end'},

                    body: {

                        stroke: '#A318FF',

                        fill: 'rgba(163, 24, 255, 0.1)',

                        rx: 28,

                        ry: 28,

                        strokeWidth: 1,

                    },

                    label: {

                        fontSize: 14,

                        fill: '#666',

                        fontWeight: 400,

                    }

                },

                ports: {

                    ...this.ports

                }

            })

            stencil.load([u3,u4], 'processLibrary')

            Graph.registerNode(

                'custom-polygon',

                {

                    inherit: 'polygon',

                    width: 80,

                    height: 50,

                    attrs: {

                    body: {

                        strokeWidth: 1,

                        stroke: '#FFAC32',

                        fill: 'rgba(255, 172, 50, 0.1)',

                    },

                    text: {

                        fontSize: 14,

                        fill: '#666666',

                    },

                    },

                    ports: {

                    ...this.ports,

                    items: [

                        {

                            group: 'top',

                        },

                        {

                            group: 'bottom',

                        },

                        {

                            group: 'right',

                        },

                        {

                            group: 'left',

                        },

                    ],

                    },

                },

                true,

            )

            const a1 = this.graph.createNode({

                shape: 'custom-polygon',

                attrs: {

                    body: {

                        refPoints: '0,10 10,0 20,10 10,20',

                    },

                },

                label: '判断',

            })

            stencil.load([a1], 'staffPool')

            this.graph.fromJSON(this.cellsData);

            let nodeArr = this.graph.getNodes()

            this.configForm = nodeArr.map((item)=>{

                let obj = {}

                obj.id = item.id

                obj.text = item.store.data.attrs.text.text

                return obj

            })

            /************************************** 绑定事件 *********************************/

            const container = document.getElementById('flowContainer')

        },

        showPorts(ports, show) {

            for (let i = 0, len = ports.length; i < len; i = i + 1) {

                ports[i].style.visibility = show ? 'visible' : 'hidden'

            }

        },

}

相关文章