在网站文字上做笔记,网站建设公司 专题制作,网页开发和网站开发一样吗,h5链接怎么做1 背景
为例描述各个服务、redis、mysql等之间的联系及其健康状态#xff0c;构建系统拓扑图#xff0c;考虑 g6 更适合处理大量数据之间的关系#xff0c;所以我们采用g6来绘制前端的图形。
g6提供的支持#xff1a;
节点/边类型多样#xff0c;同样支持自定义对于节点…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, clickkey: shift, // undefined by default, options: shift, control, ctrl, meta, altedgeConfig: {// 有该交互创建出的边的配置项可以配置边的类型、样式等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 justifystart alignmiddle 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 justifycenterButton typelink style{{ padding: 0 }} onClick{onZoomIn}ZoomInOutlined //Button/RowRow justifycenterButton typelink style{{ padding: 0 }} onClick{onZoomOut}ZoomOutOutlined //Button/RowRow justifycenterButton typelink style{{ padding: 0 }} onClick{onFixCenter}FullscreenExitOutlined //Button/Row/Col);
}