antv x6 流程图编辑实现 连线模式

antv x6 绘制流程图

因业务需要,要把节点之间的连线方式由连接桩改为键盘按键加鼠标的形式,并添加连线模式按钮。

下面来看下实现步骤,以shift键为例
  • 画布配置文件
import {Graph, Edge} from '@antv/x6'
import {message} from 'antd'

export default class FlowGraph {
    public static graph: Graph
    public static shiftPressed: boolean  //shift键是否按下
    
    //画布初始化
    public static init() {
        this.graph = new Graph({
            container: document.getElementById('container')!,
            width: 1000,
            height: 800,
            background: {color: '#040B22'},
            resizing: {
                enabled: false,
            },
            grid: {
                size: 20,
                visible: true,
                type: 'mesh',
                args: [
                    {
                        color: 'rgba(255,255,255,0.1)',
                        thickness: 1,
                    },
                ],
            },
            selecting: {
                pointerEvents: 'auto',
                enabled: true,
                multiple: true,
                rubberband: true,
                movable: false,
                showNodeSelectionBox: true,
                following: false,
            },
            connecting: {
                allowEdge: false,
                allowMulti: false,
                allowLoop: false,
                allowBlank: false,
                validateConnection({sourceView, targetView, sourceMagnet, targetMagnet}) {
                    if (sourceView === targetView) {
                        return false
                    }
                    if (!sourceMagnet) {
                        return false
                    }
                    if (!targetMagnet) {
                        return false
                    }
                    return true
                },
            },
            highlighting: {
                //高亮样式
                // 拖动节点进行嵌入操作过程中,节点可以被嵌入时被使用。
                embedding: {
                    name: 'stroke',
                    args: {
                        padding: -1,
                        attrs: {
                            stroke: '#73d13d',
                        },
                    },
                },
            },
            snapline: true,
            history: true,
            clipboard: true,
            keyboard: true,
            embedding: {
                enabled: false,
                findParent({node}) {
                    const bbox = node.getBBox()
                    return this.getNodes().filter((node) => {
                        const data = node.getData<any>()
                        if (data && data.parent) {
                            const targetBBox = node.getBBox()
                            return bbox.isIntersectWithRect(targetBBox)
                        }
                        return false
                    })
                },
            },
            scroller: {
                enabled: true,
            },
            mousewheel: {
                enabled: true,
                modifiers: ['ctrl', 'meta'],
                minScale: 0.1,
                maxScale: 3,
            },
            interacting: {
                nodeMovable: true,
            },
        })
        this.initEvent()
        return this.graph
    }


    private static initEvent() {
        const {graph} = this
   
    }

}
  • 首先画布绑定shift键按下抬起事件,按下时节点设置不可移动
private static initEvent() {
        const {graph} = this

        graph.bindKey(
            'shift',
            () => {
                FlowGraph.setShiftPressed(true)
            },
            'keydown',
        )
        graph.bindKey(
            'shift',
            () => {
                FlowGraph.setShiftPressed(false)
            },
            'keyup',
        )
    }
public static setShiftPressed(shiftPressed: boolean) {
        this.shiftPressed = shiftPressed
        if (shiftPressed) {
            (FlowGraph.graph.options.interacting as any).nodeMovable = false  // 节点不可以移动
        } else {
            (FlowGraph.graph.options.interacting as any).nodeMovable = true  // 节点可以移动
        }
    }    
  • 接着监听画布节点鼠标按下事件,先判断此时shift键是否按下,如果按下则创建连线,线的起点为按下的节点,终点为鼠标的位置,同时监听鼠标移动事件
let currentEdge: Edge

// 画布节点鼠标按下事件
graph.on("node:mousedown", ({ node, e }) => {
  // 点击节点,如果按下shift时,创建连线
  if (FlowGraph.shiftPressed) {
    currentEdge = graph.addEdge({
      source: node,
      attrs: {
        line: {
          stroke: "#d1d2db",
          strokeWidth: 1,
        },
        text: {
          type: "AUTO",
        },
      },
      router: {
        name: "manhattan",
      },
      data: {},
    });
    document.addEventListener("mousemove", handleMouseMove);

    // 创建线后,线的指向为鼠标点击的位置
    const { clientX, clientY } = e;
    const p = this.graph.clientToLocal({
      x: clientX,
      y: clientY,
    });
    currentEdge.setTarget(p);
  }
});
          
  • 鼠标移动事件,线的终点跟随鼠标位置同步更新
// 鼠标移动事件
const handleMouseMove = (e: MouseEvent) => {
  const { clientX, clientY } = e;
  const p = this.graph.clientToLocal({ x: clientX, y: clientY });
  currentEdge.setTarget(p);
};
  • 最后监听鼠标抬起事件,获取当前鼠标位置的节点,如果没有则取消连线,有则判断shift键是否仍是按下状态,然后根据业务需求进行一些场景判断最终设置线的终点
 //鼠标抬起事件
        graph.on('node:mouseup', ({node, e}) => {
            //获取鼠标位置的节点并连接
            const {clientX, clientY} = e
            const p = this.graph.clientToLocal({x: clientX, y: clientY})
            let nodes = graph.getNodesFromPoint(p.x, p.y)
            if (nodes.length) {
                if (FlowGraph.shiftPressed) {
                    document.removeEventListener('mousemove', handleMouseMove)
                    let targetNode = nodes.sort((a: any, b: any) => {
                        return b.zIndex - a.zIndex
                    })[0]
                    if (currentEdge) {
                        // 判断组合内的节点是否连接到组合外部
                        if (graph.getCellById((currentEdge.source as any).cell).getParent() != targetNode.getParent()) {
                            graph.removeEdge(currentEdge)
                            message.error('组合内的节点不能连接到外部')
                        }
                        // 判断线的终点与起点是不是同一个节点
                        if (node.id != targetNode.id) {
                            currentEdge.setTarget(targetNode)
                        } else {
                            graph.removeEdge(currentEdge)
                        }
                    }
                }
            }else {
                // 鼠标位置处没有节点,取消连线
                graph.removeEdge(currentEdge)
            }
        })
至此功能实现,当然也可以添加一个按钮来开启此模式,即点击按钮时shiftPressed设置为true即可。具体效果看以下视频,如有不足之处,请大家多多指正。

连线模式

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

bigHead-

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值