效果图
安装依赖
npm install @antv/x6 --save
我目前的项目安装的版本是@antv/x6 2.18.1
人狠话不多,直接上代码
<template><div class="er-graph-container"><!-- 画布容器 --><div ref="graphContainerRef" id="graphContainer"></div></div>
</template><script>
import { Graph, Shape } from "@antv/x6";const LINE_HEIGHT = 24;
const NODE_WIDTH = 150;export default {name: "X6GraphComponent",data() {return {graph: null,// 画布数据graphData: [{id: "1",shape: "er-rect",label: "学生",width: 150,height: 24,position: {x: 24,y: 150,},ports: [{id: "1-1",group: "list",attrs: {portNameLabel: {text: "ID",},portTypeLabel: {text: "STRING",},},},{id: "1-2",group: "list",attrs: {portNameLabel: {text: "Name",},portTypeLabel: {text: "STRING",},},},{id: "1-3",group: "list",attrs: {portNameLabel: {text: "Class",},portTypeLabel: {text: "NUMBER",},},},{id: "1-4",group: "list",attrs: {portNameLabel: {text: "Gender",},portTypeLabel: {text: "BOOLEAN",},},},],},{id: "2",shape: "er-rect",label: "课程",width: 150,height: 24,position: {x: 250,y: 210,},ports: [{id: "2-1",group: "list",attrs: {portNameLabel: {text: "ID",},portTypeLabel: {text: "STRING",},},},{id: "2-2",group: "list",attrs: {portNameLabel: {text: "Name",},portTypeLabel: {text: "STRING",},},},{id: "2-3",group: "list",attrs: {portNameLabel: {text: "StudentID",},portTypeLabel: {text: "STRING",},},},{id: "2-4",group: "list",attrs: {portNameLabel: {text: "TeacherID",},portTypeLabel: {text: "STRING",},},},{id: "2-5",group: "list",attrs: {portNameLabel: {text: "Description",},portTypeLabel: {text: "STRING",},},},],},{id: "3",shape: "er-rect",label: "老师",width: 150,height: 24,position: {x: 480,y: 350,},ports: [{id: "3-1",group: "list",attrs: {portNameLabel: {text: "ID",},portTypeLabel: {text: "STRING",},},},{id: "3-2",group: "list",attrs: {portNameLabel: {text: "Name",},portTypeLabel: {text: "STRING",},},},{id: "3-3",group: "list",attrs: {portNameLabel: {text: "Age",},portTypeLabel: {text: "NUMBER",},},},],},{id: "4",shape: "edge",source: {cell: "1",port: "1-1",},target: {cell: "2",port: "2-3",},attrs: {line: {stroke: "#A2B1C3",strokeWidth: 2,},},zIndex: 0,},{id: "5",shape: "edge",source: {cell: "3",port: "3-1",},target: {cell: "2",port: "2-4",},attrs: {line: {stroke: "#A2B1C3",strokeWidth: 2,},},zIndex: 0,},],};},mounted() {this.initGraph();},methods: {initGraph() {Graph.registerPortLayout("erPortPosition",(portsPositionArgs) => {return portsPositionArgs.map((_, index) => {return {position: {x: 0,y: (index + 1) * LINE_HEIGHT,},angle: 0,};});},true);Graph.registerNode("er-rect",{inherit: "rect",markup: [{tagName: "rect",selector: "body",},{tagName: "text",selector: "label",},],attrs: {rect: {strokeWidth: 1,stroke: "#5F95FF",fill: "#5F95FF",},label: {fontWeight: "bold",fill: "#ffffff",fontSize: 12,},},ports: {groups: {list: {markup: [{tagName: "rect",selector: "portBody",},{tagName: "text",selector: "portNameLabel",},{tagName: "text",selector: "portTypeLabel",},],attrs: {portBody: {width: NODE_WIDTH,height: LINE_HEIGHT,strokeWidth: 1,stroke: "#5F95FF",fill: "#EFF4FF",magnet: true,},portNameLabel: {ref: "portBody",refX: 6,refY: 6,fontSize: 10,},portTypeLabel: {ref: "portBody",refX: 95,refY: 6,fontSize: 10,},},position: "erPortPosition",},},},},true);this.graph = new Graph({container: this.$refs.graphContainerRef,grid: true,connecting: {router: {name: "er",args: {offset: 25,direction: "H",},},createEdge() {return new Shape.Edge({attrs: {line: {stroke: "#A2B1C3",strokeWidth: 2,},},});},},});let cells = [];this.graphData.forEach((item) => {if (item.shape === "edge") {cells.push(this.graph.createEdge(item));} else {cells.push(this.graph.createNode(item));}});this.graph.resetCells(cells);this.graph.zoomToFit({ padding: 10, maxScale: 1 });},},beforeDestroy() {this.graph && this.graph.dispose();},
};
</script><style>
/* 确保图表可以在容器内正确显示 */
.er-graph-container {min-width: 300px;min-height: 200px;
}
.er-graph-container,
#graphContainer {width: 100%;height: 100%;
}
</style>
O了