vue项目中使用antvX6新手教程,附demo案例讲解(可拖拽流程图、网络拓扑图)

前言:

之前分别做了vue2和vue3项目里的网络拓扑图功能,发现对antv X6的讲解博客比较少,最近终于得闲码一篇了!

需求:

用户可以自己拖拽节点,节点之间可以随意连线,保存拓扑图数据后传给后端,然后在另一个页面拿到之前的数据进行渲染展示。

最终成品如下图:

一、准备工作: 

1、装依赖

npm install --save @antv/x6

2、布局样式

首先我们先规划两块地方,左边用来放可以拖的节点,右边是antv X6的画布,如下图:(随意做的demo,比较丑哈)

布局代码:
<template>
  <div class="dashboard-container">
    <p>选择节点</p>
    <div class="antvBox">
      <div class="menu-list">
        <div v-for="item in moduleList" :key="item.id">
          <img :src="item.image" alt="" />
          <p>{{ item.name }}</p>
        </div>
      </div>
      <div class="canvas-card">
        <div id="container" />
      </div>
    </div>
  </div>
</template>

<script>
export default {
  name: "antvX6",
  data() {
    return {
      moduleList: [
        {
          id: 1,
          name: "节点1",
          image: require("@/assets/img/1.png"),
        },
        {
          id: 8,
          name: "节点2",
          image: require("@/assets/img/2.png"),
        },
        {
          id: 2,
          name: "节点3",
          image: require("@/assets/img/3.png"),
        },
        {
          id: 3,
          name: "节点4",
          image: require("@/assets/img/4.png"),
        },
      ],
    };
  },
};
</script>
<style lang="scss" scoped>
.dashboard-container {
  .antvBox {
    display: flex;
    width: 100%;
    height: 100%;
    color: black;
    padding-top: 20px;
    .menu-list {
      height: 100%;
      width: 300px;
      padding: 0 10px;
      box-sizing: border-box;
      display: flex;
      justify-content: space-between;
      align-content: flex-start;
      flex-wrap: wrap;
      > div {
        margin-bottom: 10px;
        border-radius: 5px;
        padding: 0 10px;
        box-sizing: border-box;
        cursor: pointer;
        color: black;
        width: 105px;
        display: flex;
        flex-wrap: wrap;

        justify-content: center;
        img {
          height: 50px;
          width: 50px;
        }
        P {
          width: 90px;
          text-align: center;
        }
      }
    }
    .canvas-card {
      width: 1700px;
      height: 750px;
      box-sizing: border-box;
      > div {
        width: 1400px;
        height: 750px;
        border: 2px dashed #2149ce;
      }
    }
  }
}
</style>

3、添加拖拽事件

我们要先给左侧图标加一个拖拽结束的事件:

代码如下:
draggable="true"
@dragend="handleDragEnd($event, item)"

在methods定义handleDragEnd函数: 

// 拖动后松开鼠标触发事件
    handleDragEnd(e, item) {
      console.log(e, item); // 可以获取到最后拖动后松开鼠标时的坐标和拖动的节点相关信息
    },
效果 :

这个时候我们可以去页面试着拖动一个左边的图标,在鼠标松开时会看到控制台输出了节点相关信息,如下图:

 以上就是准备工作了

二、使用antv X6

1、引入antv X6

import { Graph } from "@antv/x6";

2、初始化画布

先在data(){}定义graph做画布示例对象:

定义一个初始化函数,并且在mounted里面调用如下:

initGraph() {
      const container = document.getElementById("container");
      this.graph = new Graph({
        container: container, // 画布容器
        width: container.offsetWidth, // 画布宽
        height: container.offsetHeight, // 画布高
        background: false, // 背景(透明)
        snapline: true, // 对齐线
        // 配置连线规则
        connecting: {
          snap: true, // 自动吸附
          allowBlank: false, // 是否允许连接到画布空白位置的点
          allowMulti: true, // 是否允许在相同的起始节点和终止之间创建多条边
          allowLoop: true, // 是否允许创建循环连线,即边的起始节点和终止节点为同一节点
          highlight: true, // 拖动边时,是否高亮显示所有可用的节点
          highlighting: {
            magnetAdsorbed: {
              name: "stroke",
              args: {
                attrs: {
                  fill: "#5F95FF",
                  stroke: "#5F95FF",
                },
              },
            },
          },
          router: {
            // 对路径添加额外的点
            name: "orth",
          },
          connector: {
            // 边渲染到画布后的样式
            name: "rounded",
            args: {
              radius: 8,
            },
          },
        },
        panning: {
          enabled: false,
        },
        mousewheel: {
          enabled: true, // 支持滚动放大缩小
          zoomAtMousePosition: true,
          modifiers: "ctrl",
          minScale: 0.5,
          maxScale: 3,
        },
        grid: {
          type: "dot",
          size: 20, // 网格大小 10px
          visible: true, // 渲染网格背景
          args: {
            color: "#a0a0a0", // 网格线/点颜色
            thickness: 2, // 网格线宽度/网格点大小
          },
        },
      });
    },
 mounted() {
    this.initGraph();
  },

这里就是一些对画布的配置,多数我都加了注释,如有部分配置不懂可以评论区问我或者查官方文档

3、画布添加节点

代码如下:

 //添加节点到画布
    addHandleNode(x, y, id, image, name) {
      this.graph.addNode({
        id: id,
        shape: "image", // 指定使用何种图形,默认值为 'rect'
        x: x,
        y: y,
        width: 60,
        height: 60,
        imageUrl: image,
        attrs: {
          body: {
            stroke: "#ffa940",
            fill: "#ffd591",
          },
          label: {
            textWrap: {
              width: 90,
              text: name,
            },
            fill: "black",
            fontSize: 12,
            refX: 0.5,
            refY: "100%",
            refY2: 4,
            textAnchor: "middle",
            textVerticalAnchor: "top",
          },
        },
        ports: {
          groups: {
            group1: {
              position: [30, 30],
            },
          },
          items: [
            {
              group: "group1",
              id: "port1",
              attrs: {
                circle: {
                  r: 6,
                  magnet: true,
                  stroke: "#ffffff",
                  strokeWidth: 2,
                  fill: "#5F95FF",
                },
              },
            },
          ],
        },
        zIndex: 10,
      });
    },

这里使用了antv X6提供的一个方法addNode,传入的参数分别是:x坐标、y坐标、id节点唯一标识、image图片、name节点名称,我的案例这五种就够了,如果有不同需求可以自己加

4、调用addHandleNode函数

在我们之前写了的拖动节点结束后的函数(handleDragEnd)里面去调用上面那个函数,代码如下:

// 拖动后松开鼠标触发事件
    handleDragEnd(e, item) {
      console.log(e, item); // 可以获取到最后拖动后松开鼠标时的坐标和拖动的节点相关信息
      this.addHandleNode(
        e.pageX - 500,
        e.pageY - 200,
        new Date().getTime(),
        item.image,
        item.name
      );
    },

以上所有操作做完应该就可以完成节点拖拽、连线功能:

5、上图我们可以发现还差一些需求:

  • 节点上的那个蓝色的连接桩一直显示,有点遮挡图标,也不太好看

  • 节点无法删除

  • 节点之间的连线也无法删除

这些都是需要点击操作的事件,需要了解antv X6的事件系统,官方文档贴图如下

需求1:鼠标移入节点再显示连接桩

定义一个函数nodeAddEvent,代码如下:

nodeAddEvent() {
      const { graph } = this;
      const container = document.getElementById("container");
      const changePortsVisible = (visible) => {
        const ports = container.querySelectorAll(".x6-port-body");
        for (let i = 0, len = ports.length; i < len; i = i + 1) {
          ports[i].style.visibility = visible ? "visible" : "hidden";
        }
      };
      this.graph.on("node:mouseenter", () => {
        changePortsVisible(true);
      });
      this.graph.on("node:mouseleave", () => {
        changePortsVisible(false);
      });
    },

然后把这个函数在initGraph里面调用一下:

效果如下:

 

需求2:可以选中并删除节点

想要的效果如下图:

先在data(){}里面定义curSelectNode,然后在nodeAddEvent函数里加入以下代码:

// 节点绑定点击事件
      this.graph.on("node:click", ({ e, x, y, node, view }) => {
        console.log("点击!!!", node);
        // 判断是否有选中过节点
        if (this.curSelectNode) {
          // 移除选中状态
          this.curSelectNode.removeTools();
          // 判断两次选中节点是否相同
          if (this.curSelectNode !== node) {
            node.addTools([
              {
                name: "boundary",
                args: {
                  attrs: {
                    fill: "#16B8AA",
                    stroke: "#2F80EB",
                    strokeWidth: 1,
                    fillOpacity: 0.1,
                  },
                },
              },
              {
                name: "button-remove",
                args: {
                  x: "100%",
                  y: 0,
                  offset: {
                    x: 0,
                    y: 0,
                  },
                },
              },
            ]);
            this.curSelectNode = node;
          } else {
            this.curSelectNode = null;
          }
        } else {
          this.curSelectNode = node;
          node.addTools([
            {
              name: "boundary",
              args: {
                attrs: {
                  fill: "#16B8AA",
                  stroke: "#2F80EB",
                  strokeWidth: 1,
                  fillOpacity: 0.1,
                },
              },
            },
            {
              name: "button-remove",
              args: {
                x: "100%",
                y: 0,
                offset: {
                  x: 0,
                  y: 0,
                },
              },
            },
          ]);
        }
      });

这里使用了antv X6的工具集,官方文档贴图如下:(需求3也使用了工具集)

需求3:可以选中并删除节点间连线

 想要的效果如下:

在nodeAddEvent函数里加入以下代码:

 // 连线绑定悬浮事件
      this.graph.on("cell:mouseenter", ({ cell }) => {
        if (cell.shape == "edge") {
          cell.addTools([
            {
              name: "button-remove",
              args: {
                x: "100%",
                y: 0,
                offset: {
                  x: 0,
                  y: 0,
                },
              },
            },
          ]);
          cell.setAttrs({
            line: {
              stroke: "#409EFF",
            },
          });
          cell.zIndex = 99; // 保证当前悬停的线在最上层,不会被遮挡
        }
      });
      this.graph.on("cell:mouseleave", ({ cell }) => {
        if (cell.shape === "edge") {
          cell.removeTools();
          cell.setAttrs({
            line: {
              stroke: "black",
            },
          });
          cell.zIndex = 1; // 保证未悬停的线在下层,不会遮挡悬停的线
        }
      });

6、输出拓扑图信息

可以写一个按钮来保存拓扑图信息,这里介绍以下两个个人感觉常用的函数:

//保存画布,并提交
    save() {
      console.log(this.graph.toJSON(), "graph");
      console.log(this.graph.getNodes(), "node");
    },

如上图所示,点击保存按钮后 ,控制台会输出:

第一个是整个图的信息,有节点有连线,可以自己展开看看里面的数据,第二个只有节点数据

四、总结

antv X6 是基于 HTML 和 SVG 的图编辑引擎,提供低成本的定制能力和开箱即用的内置扩展,方便我们快速搭建 DAG 图、ER 图、流程图、血缘图等应用。

这里只是介绍了一种基础拓扑图的案例,也可以将节点image换成react,做一个编辑节点内文字的功能,就变成流程图了。

查看官方文档和示例,也很容易加入其他的功能

antv X6案例链接:https://x6.antv.antgroup.com/examples

api文档:Graph | X6 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/428189.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

力扣61:旋转链表

题目 给你一个链表的头节点 head &#xff0c;旋转链表&#xff0c;将链表每个节点向右移动 k 个位置。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5], k 2输出&#xff1a;[4,5,1,2,3] 示例 2&#xff1a; 输入&#xff1a;head [0,1,2], k 4输出&#xff1a;…

【硬件相关】Mellanox网络配置及参数优化

文章目录 一、前言1、硬件配置2、网卡信息 二、驱动安装1、驱动介绍2、软件架构2.1、mlx4 VPI Driver2.2、mlx5 Driver 3、驱动安装3.1、常规安装3.2、驱动编译方法一方法二 4、RDMA配置 三、交换机配置四、mlnx-tools管理工具1、软件安装2、软件使用ibdev2netdeva、说明b、用法…

【MySQL系列】在 MacOS 上安装 MySQL

在 MacOS 上有两种方式安装 MySQL 服务器&#xff1a;通过 brew 安装和通过安装包安装。 文章目录 1、通过 brew 安装 MySQL1.1、安装 MySQL1.2、启动 MySQL 服务器1.3、配置 MySQL 服务器1.4、MySQL 服务器管理命令 2、通过安装包安装 MySQL2.1、下载安装包2.2、安装 MySQL2.3…

Vue3:使用 Composition API 不需要 Pinia

在 Vue.js 开发的动态环境中&#xff0c;在单个组件中处理复杂的业务逻辑可能会导致笨重的文件和维护噩梦。虽然 Pinia 提供集中式状态管理&#xff0c;但仅依赖它来处理复杂的业务逻辑可能会导致代码混乱。本文探讨了使用 Composition API 的替代方法&#xff0c;说明开发人员…

mysql学习笔记5——对表的修改操作

对表的列进行操作 对表可以进行创建create与删除drop&#xff0c;同时可以对表进行修改alter 修改字段 添加字段 删除具体的某一列 添加列时可以指定添加位置 对表的数据进行操作 select查询操作可以指定查询条件 删除具体数据&#xff08;而非删除表中某一列某一行&#xf…

【重要公告】对BSV警报系统AS的释义

​​发表时间&#xff1a;2024年2月15日 由BSV区块链协会开发并管理的BSV警报系统&#xff08;Alert System&#xff0c;以下简称“AS”&#xff09;是BSV网络的重要组件。它是一个复杂的系统&#xff0c;主要职能是在BSV区块链网络内发布信息。这些信息通常与网络访问规则NAR相…

ChatGPT论文指南|ChatGPT如何助力论文中的数据分析!【建议收藏】

点击下方▼▼▼▼链接直达AIPaperPass &#xff01; AIPaperPass - AI论文写作指导平台 公众号原文▼▼▼▼&#xff1a; ChatGPT论文指南|ChatGPT如何助力论文中的数据分析&#xff01;【建议收藏】 小编在之前的论文写作流程中&#xff0c;介绍了大量论文文字工作&#xff…

VUE引入高德地图区域划分district结果为空(Cannot read properties of undefined (reading ‘0‘))

1.错误 Uncaught TypeError: Cannot read properties of undefined (reading 0) 通过debugger去看status、result结果status为no_data,而result为空 2.原因 大概率就是key过期了或者配置错了 3.正确配置 </script> <!-- 注意&#xff1a;导入密钥要在接口上面&…

2024.3.4 作业

1、流式域套接字 1>tcp服务端实现 #include<myhead.h> int main(int argc, const char *argv[]) {//1、创建套接字int sfd socket(AF_UNIX, SOCK_STREAM, 0);if(sfd -1){perror("socket error");return -1;}//2、判断套接字文件是否存在&#xff0c;如果…

史上最细,企业性能测试步骤详细,测试老鸟带你一篇打通!

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 1、性能测试流程 …

总线要点笔记

1. AXI/AHB/APB差异 AMBA (Advanced Microcontroller Bus Architecture) 高级处理器总线架构 AHB (Advanced High-performance Bus) 高级高性能总线 ASB (Advanced System Bus) 高级系统总线 APB (Advanced Peripheral Bus) 高级外围总线 AXI (Advanced eXtensible Interface) …

【洛谷 P8682】[蓝桥杯 2019 省 B] 等差数列 题解(数学+排序+差分)

[蓝桥杯 2019 省 B] 等差数列 题目描述 数学老师给小明出了一道等差数列求和的题目。但是粗心的小明忘记了一部分的数列&#xff0c;只记得其中 N N N 个整数。 现在给出这 N N N 个整数&#xff0c;小明想知道包含这 N N N 个整数的最短的等差数列有几项&#xff1f; 输…

探究大语言模型如何使用长上下文

&#x1f349; CSDN 叶庭云&#xff1a;https://yetingyun.blog.csdn.net/ 论文链接&#xff1a;https://doi.org/10.1162/tacl_a_00638 论文标题&#xff1a;Lost in the Middle: How Language Models Use Long Contexts 论文发表期刊&#xff1a;Transactions of the Assoc…

【Apple Vision Pro应用】Cinephile——Cinema Mode for Local Video(苹果眼睛视频播放器)

Cinephile 为您提供了一个完全无干扰、无限制的无限空间&#xff0c;让您尽享视频的精彩。它创造了一种身临其境的环境&#xff0c;您可以在能够想象到的最大屏幕上&#xff0c;从任何角度或位置观看内容。 您可以根据个人喜好自由调整视频的大小和位置。添加视频中的环境光&am…

MoonBit 新增 += 运算符,引入 super trait 和 List 字面量机制

MoonBit更新 1. 添加了 系列语句 包括、-、*、/&#xff0c;支持运算符重载&#xff1a; fn init {let array [1,2,3,4]array[2] * 10println(array) // [1, 2, 30, 4] }fn init {let mut a 1a 20println(a) // 21 } struct Foo {data : Array[Int] } derive(Debug)fn o…

转载-七种Java常用序列化框架的选型与对比

七种Java常用序列化框架的选型与对比 本文章转自&#xff1a;乐字节 文章主要讲解&#xff1a;Java常用序列化框架 获取更多前端相关资料可以点击链接加入群聊【Java技术交流群】&#xff1a;正在跳转暗号&#xff1a;166 转载地址&#xff1a;七种Java常用序列化框架的选型…

Linux设备模型(九) - bus/device/device_driver/class

一&#xff0c;设备驱动模型 1&#xff0c;概述 在前面写的驱动中&#xff0c;我们发现编写驱动有个固定的模式只有往里面套代码就可以了&#xff0c;它们之间的大致流程可以总结如下&#xff1a; 实现入口函数xxx_init()和卸载函数xxx_exit() 申请设备号 register_chrdev_r…

软件测试的基本流程是什么?软件测试流程详细介绍

软件测试和软件开发一样&#xff0c;是一个比较复杂的工作过程&#xff0c;如果无章法可循&#xff0c;随意进行测试势必会造成测试工作的混乱。为了使测试工作标准化、规范化&#xff0c;并且快速、高效、高质量地完成测试工作&#xff0c;需要制订完整且具体的测试流程。 01…

中国各省绿色金融试点DID数据集(2010-2023)

一、数据简介 最新的2010-2023年中国31省绿色金融试点DID数据&#xff0c;供大家研究使用。 数据说明&#xff1a;内含绿色金融改革创新试验区名单&#xff0c;将试验区获批当年及以后的政策虚拟变量项是否试点赋值为1&#xff0c;获批之前赋值为0。其中赣江新区、贵安新区为国…

Spring:FactoryBean预加载逻辑以及自定义实现Mybatis的接口扫描

Spring&#xff1a;FactoryBean预加载逻辑以及自定义实现Mybatis的接口扫描 1 前言 参考Mybatis框架的Mapper注解扫描Mapper接口的业务逻辑&#xff0c;其中集成Spring的逻辑里使用到了Spring框架的FactoryBean拓展点&#xff0c;本文针对Spring FactoryBean的加载流程进行分…