antv g6实现系统拓扑图

1 背景

为例描述各个服务、redis、mysql等之间的联系及其健康状态,构建系统拓扑图,考虑 g6 更适合处理大量数据之间的关系,所以我们采用g6来绘制前端的图形。

g6提供的支持:

  • 节点/边类型多样,同样支持自定义
  • 对于节点的样式可以直接配置化处理
  • 丰富的事件体系,包括对节点/边/画布,以及时机事件的监听
  • 多种布局算法
  • 节点/边的数据,都是可以配置化的json对象

在线工具:g6示例

2 功能列表

节点:

  • 添加节点:除了id、style、type外,还包括一些业务需要的数据
  • 删除节点:除了删除该节点相对于画布的id外,还包括与之相关的业务数据
  • 节点状态:比如错误节点需要标红;非活跃节点需要标灰

边:

  • 添加边:除了id、style、type外,还包括一些业务需要的数据
  • 删除变:除了删除该边相对于画布的id外,还包括与之相关的业务数据
  • 修改边:主要是修改边所代表的业务信息,如果没有业务信息的话,这条边应该被删除

画布:

  • 用户自定义布局,比如需要保存用户拖拽节点后的节点位置坐标信息
  • dagre层次布局
  • 工具栏
  • 图例
  • 小地图
  • 触摸板放大缩小
  • 节点搜索

3 节点

3.1 渲染节点

渲染节点,包括自定义节点类型和样式。

自定义节点,该节点由rect和image组成,类似于矩形里面有icon:

// 其实可以不用自定义节点,可以使用circle类型的icon字段。但是这种方式,点击节点的时候,里面的icon会存在闪缩的情况
// https://g6.antv.antgroup.com/manual/middle/elements/nodes/built-in/circle#%E5%9B%BE%E6%A0%87-icon
G6.registerNode('drag-inner-image-node',{afterDraw(cfg, group) {const size = cfg?.size as number[];const width = size[0] - 20;const height = size[1] - 20;const imageShape = group?.addShape('image', {attrs: {x: -width / 2,y: -height / 2,width,height,img: cfg?.img,cursor: 'move',},// must be assigned in G6 3.3 and later versions. it can be any string you want, but should be unique in a custom item typename: 'image-shape',});// 启用拖拽imageShape?.set('draggable', true);},},'circle',
);

节点样式:

const DefaultNodeSelectedStyle = {lineWidth: 8,'text-shape': {// 点击后的文本样式,保持点击前一致fontWeight: 400,},
};export const NodeStyleMap = {default: {// 正常节点 - 样式设置style: {fill: GlobalLightBlueColor,stroke: GlobalBlueColor,lineWidth: 1,},// 状态样式,比如 selected点击状态stateStyles: {selected: {stroke: GlobalBlueColor,fill: GlobalLightBlueColor,shadowColor: GlobalBlueColor,...DefaultNodeSelectedStyle,},},},error: {// 异常节点style: {stroke: GlobalRedColor,fill: GlobalLightRedColor,lineWidth: 1,},stateStyles: {selected: {stroke: GlobalRedColor,fill: GlobalLightRedColor,shadowColor: GlobalRedColor,...DefaultNodeSelectedStyle,},},},
};

获取节点的渲染数据:

export const formatNodes = (nodes: MttkArchitectureNode[] = []) => {return nodes?.map((node) => {const { component, has_error, coordinates } = node;// 业务逻辑const middlewareType = getMiddlewareType(component) as MttkComponentType;const { id, label, wholeLabelName } = getNodeId(node);// 样式和iconconst nodeStyle = NodeStyleMap[has_error ? 'error' : 'default'];const img = has_error ? ErrorIconImageMap[middlewareType] : IconImageMap[middlewareType];return {...node,img,middlewareType,label,wholeLabelName, // 仅前端展示使用...nodeStyle,id, // 仅前端展示使用x: coordinates?.x, // 节点的位置坐标y: coordinates?.y, // 节点的位置坐标};});
};

3.2 删除节点

3.3 添加节点

4 边

4.1 渲染边

边的样式:

const DefaultEdgeSelectedStyle = {lineWidth: 4,shadowBlur: 10, // 阴影的模糊级别,数值越大越模糊
};export const EdgeStyleMap = {default: {// 正常边 - 样式设置style: {stroke: GlobalBlueColor,lineWidth: 1,lineDash: [0], // 如果[0]表示直线,需要覆盖一下创建边之后的虚线样式},// 状态样式,比如 selected点击状态stateStyles: {selected: {stroke: GlobalBlueColor,shadowColor: GlobalBlueColor,...DefaultEdgeSelectedStyle,},},},error: {// 异常边style: {stroke: GlobalRedColor,lineWidth: 1,},stateStyles: {selected: {stroke: GlobalRedColor,shadowColor: GlobalRedColor,...DefaultEdgeSelectedStyle,},},},
};

边的渲染数据:

export const formatEdges = (edges: MttkArchitectureEdge[] = [], nodes: MttkArchitectureNode[] = []) => {return edges?.map((edge) => {const { has_error } = edge;const edgeStyle = EdgeStyleMap[has_error ? 'error' : 'default'];const { id, fromId, toId } = getEdgeId(nodes, edge);return {...edge,source: fromId,target: toId,...edgeStyle,id,from: fromId, // 前端直接替换掉get接口返回的随机数idto: toId, // 前端直接替换掉get接口返回的随机数id};});
};

4.2 删除边

4.3 添加边

5 画布全局配置


export const LayoutMap = {[LayoutType.LR]: {// 从左到右type: 'dagre',ranksep: 70,controlPoints: true, // 是否保留布局连线的控制点rankdir: 'LR', // 可选,默认为图的中心nodesep: 10, // 可选},[LayoutType.TB]: {// 从上到下// type: 'dagre',// ranksep: 70,// controlPoints: true,rankdir: 'TB',},
};export const DefaultOptions = {layout: LayoutMap.LR,defaultNode: {type: 'drag-inner-image-node',size: [50, 50],style: { cursor: 'move' },label: 'node-label',labelCfg: {position: 'bottom',offset: 2,style: {fill: '#666',fontSize: 14,cursor: 'move',},},},defaultEdge: {type: 'polyline',style: {radius: 20, // 拐弯处的圆角弧度offset: 20, // 拐弯处距离节点最小距离endArrow: true,lineAppendWidth: 20, // 提升边的击中范围},},modes: {default: ['drag-canvas','drag-node',{type: 'create-edge',trigger: 'click', // 'click' by default. options: 'drag', 'click'key: 'shift', // undefined by default, options: 'shift', 'control', 'ctrl', 'meta', 'alt'edgeConfig: {// 有该交互创建出的边的配置项,可以配置边的类型、样式等style: {radius: 20, // 拐弯处的圆角弧度offset: 20, // 拐弯处距离节点最小距离endArrow: true,lineAppendWidth: 20, // 提升边的击中范围...EdgeStyleMap.default.style,lineDash: [5], // 设置线的虚线样式, 如果[0]表示直线},},shouldEnd: (e: any, self: any) => {const { item: toItem } = e;const { source: fromId, graph } = self;const toId = toItem._cfg.id;// 不允许创建自环边if (toId === fromId) {return false;}// 不允许创建已经存在的边const edges = graph.getEdges();if (edges.some((ed: any) => {const { source, target } = ed.getModel();return fromId === source && toId === target;})) {return false;}return true;},},{type: 'click-select',// 不允许节点被该交互选中。如果为true的话,会存在重复点击当前节点闪烁的情况,// 因为 已选中 > 再次点击,会默认给当前节点 selected status设置为false,我们再手动改为true的时候,就会存在闪烁selectNode: false,multiple: false, // 不允许多选},],},fitView: true, // 图是否自适应画布
};

6 图例

g6自带的图例不是很好自定义ui,虽然可以进行与节点/边数据联动的功能,所以考虑直接react实现。

// interface Props {
//   extendLegend?: React.ReactNode; // 扩展图例,比如错误的信息
// }
export const GraphNodeTypeConfigs = [{icon: IconImageMap[MttkComponentType.SERVICE],description: 'Service',key: MttkComponentType.SERVICE,},{icon: IconImageMap[MttkComponentType.MYSQL],description: 'MySQL',key: MttkComponentType.MYSQL,},{icon: IconImageMap[MttkComponentType.KAFKA],description: 'Kafka',key: MttkComponentType.KAFKA,},{icon: IconImageMap[MttkComponentType.REDIS],description: 'Redis',key: MttkComponentType.REDIS,},{icon: IconImageMap[MttkComponentType.UNKNOWN],description: 'Unknown',key: MttkComponentType.UNKNOWN,},
];export function LegendRow() {return (<>{GraphNodeTypeConfigs.map(({ icon, description }) => (<Row justify="start" align="middle" wrap={false} style={{ marginRight: 8 }}><img src={icon} style={{ width: 18, height: 18, marginRight: 4 }} />{description}</Row>))}</>);
}

7 工具栏

跟图例一样,考虑不太好自定义ui,所以直接react实现。

import { ZoomInOutlined, ZoomOutOutlined, FullscreenExitOutlined } from '@ant-design/icons';
import { Col, Row, Button } from 'antd';interface Props {onZoomIn: () => void; // 放大onZoomOut: () => void; // 缩小onFixCenter: () => void; // 回到中间
}export function Toolbar(props: Props) {const { onZoomIn, onZoomOut, onFixCenter } = props;return (<Col style={{ width: 30 }}><Row justify="center"><Button type="link" style={{ padding: 0 }} onClick={onZoomIn}><ZoomInOutlined /></Button></Row><Row justify="center"><Button type="link" style={{ padding: 0 }} onClick={onZoomOut}><ZoomOutOutlined /></Button></Row><Row justify="center"><Button type="link" style={{ padding: 0 }} onClick={onFixCenter}><FullscreenExitOutlined /></Button></Row></Col>);
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Sping源码(九)—— Bean的初始化(非懒加载)— Bean的创建方式(factoryMethod)

序言 前面文章介绍了在Spring中多种创建Bean实例的方式&#xff0c;包括采用FactoryBean的方式创建对象、使用反射创建对象、自定义BeanFactoryPostProcessor。 这篇文章继续介绍Spring中创建Bean的形式之一——factoryMethod。方法用的不多&#xff0c;感兴趣可以当扩展了解。…

【Git】--Part3--远程操作 配置 标签管理

1. 远程仓库 Git 是分布式版本控制系统&#xff0c;同⼀个 Git 仓库&#xff0c;可以分布到不同的机器上。怎么分布呢&#xff1f; 最早&#xff0c;肯定只有⼀台机器有⼀个原始版本库&#xff0c;此后&#xff0c;别的机器可以 “克隆” 这个原始版本库&#xff0c;⽽且每台机…

JEnv-for-Windows 详细使用

管理员执行jenv.bat文件 执行正常, 接下来就是按照官网的命令就行了 文件下载地址 https://download.csdn.net/download/qq_43071699/89462664 JEnv 是一个强大的Java版本管理工具&#xff0c;允许开发者在多个Java版本之间轻松切换。以下是一些常用的JEnv命令&#xff0c;这…

118 杨辉三角

题目 给定一个非负整数 numRows&#xff0c;生成「杨辉三角」的前 numRows 行。 在「杨辉三角」中&#xff0c;每个数是它左上方和右上方的数的和。 示例 输入: numRows 5 输出: [[1],[1,1],[1,2,1],[1,3,3,1],[1,4,6,4,1]] 解析 就是模拟法&#xff0c;没有什么特殊的…

【原创】EtherCAT主站IgH解析(二)-- Linux/Windows/RTOS等多操作系统IgH EtherCAT主站移植指南

版权声明&#xff1a;本文为本文为博主原创文章&#xff0c;转载请注明出处 https://www.cnblogs.com/wsg1100 如有错误&#xff0c;欢迎指正。 ##前言 目前&#xff0c;EtherCAT商用主站有&#xff1a;Acontis、TwinCAT3、KPA、Codesys等&#xff0c;开源EtherCAT主站则主要…

一文教你在centos 7.9中安装mysql5.7(超级详细)

##red## &#x1f534; 大家好&#xff0c;我是雄雄&#xff0c;欢迎关注微信公众号&#xff0c;雄雄的小课堂。 一、前言 每当新来一个服务器之后&#xff0c;习惯性的都会安装一个宝塔面板&#xff0c;不为别的&#xff0c;就为了装环境方便点儿&#xff0c;比如常用的jdk,m…

HbuildX的发行有什么用?

在微信开发者工具中上传主包时&#xff0c;如果文件大小超过了2MB的限制&#xff0c;可能是由于打包过程中的没有优化和压缩 HBuilder X 在发布环节会对代码和资源进行一系列处理&#xff0c;例如去除不必要的 代码&#xff0c;压缩图片、CSS和JavaScript 等资源&#xff0c;以…

C#学习系列之ListView垂直滚动

C#学习系列之ListView垂直滚动 前言垂直滚动总结 前言 当ListView中不断增加新内容&#xff0c;经常是纵向滚动。 垂直滚动 这个是关键&#xff1a;<VirtualizingStackPanel/> <ListView.ItemsPanel><ItemsPanelTemplate><VirtualizingStackPanel/>&…

C++学习(23)

#学习自用# union 共用体和结构体相似&#xff0c;但是共用体一次只能占用一个成员的内存&#xff0c;所有成员共用同一地址。 #include<iostream> using namespace std; union A {int int_val;float float_val; }a; int main() {a.float_val 2.0f;cout << a.f…

【免费API推荐】:解锁无限创意,让您的应用更具竞争力(8)

热门高效的免费实用类API是当今开发者们追逐的宝藏。这些API提供了各种热门功能和服务&#xff0c;能够帮助开发者轻松地为应用程序增添实用性和吸引力。无论是人脸识别、自然语言处理、机器学习还是图像处理&#xff0c;这些热门高效的免费API提供了强大的功能和高效的性能&am…

vuejs3+elementPlus后台管理系统,左侧菜单栏制作、跳转、默认激活菜单

制作&#xff1a; <script setup> import {useUserStore} from "/stores/userStore.js"; import {ref} from "vue";const userStore useUserStore() //默认激活菜单 const defaultMenu ref(/home) </script><template><el-menuact…

Redis 主从复制+哨兵+集群

Redis复制 查看docker 容器 ip docker inspect 容器id | grep IPAddressdocker inspect -f{{.Name}} {{.NetworkSettings.IPAddress}} $(docker ps -aq)修改配置文件 初始配置文件见 > redis.conf 远程访问 bind 0.0.0.0protected-mode no 主机设置 replicaof 172.17.0.…

Vue66-vue-默认插槽

一、默认插槽需求 1-1、原本的写法&#xff1a; 在每个category组件中用v-show来做条件渲染&#xff0c;但是不方便&#xff01; 1-2、默认插槽 img标签&#xff0c;ul标签&#xff0c;video标签&#xff0c;都是在app组件中完成解析之后&#xff0c;塞到category组件中的&…

汉朔科技IPO:引领智慧零售新时代,推动行业数字化转型

汉朔科技是一家以物联网无线通信技术为核心的高新技术企业&#xff0c;围绕零售门店数字化领域&#xff0c;构建了以电子价签系统、SaaS云平台服务等软硬件产品及服务为核心的业务体系。凭借公司技术实力、战略布局和多年行业积累&#xff0c;汉朔科技成为了零售门店数字化解决…

蓝鹏测控公司全长直线度算法项目多部门现场组织验收

关键字:全场直线度算法,直线度测量仪,直线度检测,直线度测量设备, 6月18日上午&#xff0c;蓝鹏测控公司全长直线度算法项目顺利通过多部门现场验收。该项目由公司技术部、开发部、生产部等多个部门共同参与&#xff0c;旨在提高直线度测量精度&#xff0c;满足高精度制造领域需…

Redis分片集群搭建

主从模式可以解决高可用、高并发读的问题。但依然有两个问题没有解决&#xff1a; 海量数据存储高并发写 要解决这两个问题就需要用到分片集群了。分片的意思&#xff0c;就是把数据拆分存储到不同节点&#xff0c;这样整个集群的存储数据量就更大了。 Redis分片集群的结构如…

LVGL使用GUI Guider配置STM32界面详细笔记教程

0、说明 接着前面几篇博客对LVGL的使用和介绍&#xff0c;这篇博客主要是使用和介绍快速配置LVGL图形界面编程的工具&#xff0c;GUI Guider。本文使用的工程代码&#xff0c;均是基于前几篇博客的基础上的&#xff0c;如需下载已配置好的LVGL-MCU工程环境&#xff0c;可通过如…

【R语言】对一个Plot绘制多个图,并且每个图单元也包含多个图

以一个Plot绘制五行六列共30个图&#xff0c;然后每30个图单元包含两个图为例&#xff1a; 如下图所示&#xff1a; 代码如下&#xff1a; for (i in 1:(5*6)) {create_subplots <- function() {library(ggplot2)library(dplyr)library(tidyr)# 创建一个随机的数据框simula…

【机器学习】机器学习重要方法—— 半监督学习:理论、算法与实践

文章目录 引言第一章 半监督学习的基本概念1.1 什么是半监督学习1.2 半监督学习的优势 第二章 半监督学习的核心算法2.1 自训练&#xff08;Self-Training&#xff09;2.2 协同训练&#xff08;Co-Training&#xff09;2.3 图半监督学习&#xff08;Graph-Based Semi-Supervise…

【服务器04】之【Navicat连接阿里云】

通过前三篇文章&#xff0c;现在我们测试可以连接数据库了 点开桌面的 接下找来的主机 地址在以下 登录阿里云 登陆账号后 点击控制台 输入RDS 弹出新页面&#xff0c;并点击运行中的 1 点管理 复制外网地址 鼠标靠近就会出现复制图标 用户名 和 密码 是注册阿里云的高权限账…