700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > vue使用svg画拓扑图(关系图) 拖拽 缩放

vue使用svg画拓扑图(关系图) 拖拽 缩放

时间:2024-06-07 17:15:14

相关推荐

vue使用svg画拓扑图(关系图) 拖拽 缩放

概述

项目刚开始用的echarts画的拓扑图,echarts有个关系图可以直接画出来,但是上个前端在拖拽功能上留了bug,我眼睛都快看瞎了,都没找出来哪里出问题,还找了各种文章借鉴学习都没搞定

后来跑到gitHub上面找了个大神写的拓扑,根据他的代码改好了,不过他用的svg画的图,所以我这份记录也是svg

注意

数据从后端获取,模拟数据已经提供,修改getData()中代码就行缩放功能用到了d3,先安装npm install d3 --save-devmain.js中引入import * as d3 from 'd3'; Vue.prototype.$d3 = d3图片自己随便弄,注意图片名字和后缀名就行

代码

HTML

<template><div class="content"><!--拓扑存放位置--><svgclass="topo"id="svg"ondragover="return false"oncontextmenu="return true"@mousewheel="zooming"><!-- 已连接的线 --><linev-for="(item) in lines":key="item.x":x1="item.x1" :y1="item.y1":x2="item.x2" :y2="item.y2"style="stroke:rgb(214,214,218);stroke-width:2"/><gv-for="(item, index) in topoNodes":key="item.id"@mousedown.left.stop.prevent="moveAndLink(index, $event)"><image :xlink:href="item.symbol" width="50px" height="50px" :x="item.x" :y="item.y"></image><text :x="item.x + 25" :y="item.y + 66" style="text-anchor: middle; user-select: none;">{{item.name}}</text></g></svg></div></template>

JavaScript

<script>export default {name: 'SvgDemo',props: {},data() {return {res: {code: 200,data: [{name: "default",devices: [{id: "3",name: "Router",ip: "169.254.200.2",type: "router",x: 400,y: 50},{id: "1",name: "Linux",ip: "192.168.67.101",type: "server",x: 52,y: 500},{id: "5",name: "Winserver",ip: "192.168.67.200",type: "server",x: 500,y: 500},{id: "4",name: "SW",ip: "192.168.67.201",type: "switch",x: 200,y: 200}],relation: [{source: "3", target: "4", network: "Net-CSRiface_1"},//连线——————source:起点,target(目标):终点{source: "1", target: "4", network: "Net-SWiface_16"},{source: "5", target: "4", network: "Net-R4iface_0"}]}]},topoNodes: [], // topo图中的节点topoLinks: [], // topo图中的连线isMove: true,// 操作模式,默认为移动。可切换为连接模式positions: [],//更改的位置token: null}},computed: {// 动态计算节点间的连线lines() {let hash = {}const OFFSET = 20this.topoNodes.forEach((item, index) => {hash[item.id] = index})/*hash:{1: 13: 04: 35: 2},source:3 1 5,target:4 4 4*/return this.topoLinks.map(item => {const startNode = this.topoNodes[hash[Number(item.source)]]const endNode = this.topoNodes[hash[Number(item.target)]]return {x1: startNode.x + OFFSET,y1: startNode.y + OFFSET,x2: endNode.x + OFFSET,y2: endNode.y + OFFSET,}})}},created() {this.token = sessionStorage.getItem("token");this.getData();},methods: {getData() {//使用模拟数据/*this.topoNodes = this.res.data[0].devices;this.topoLinks=this.res.data[0].relation;for (let item of this.topoNodes) {item.symbol = require(`@/assets/images/${item.type}.svg`);}for (let item of this.topoLinks) {item.source = Number(item.source);item.target=Number(item.target);}console.log(this.topoNodes)*///使用接口返回数据this.$axios({url: window.config.Login_URL + "/mirror/spaces/topology", //topologymethod: "GET",headers: {MyToken: this.token,},data: {status: this.value,},}).then((res) => {if (res.data.code === 200) {this.topoNodes = res.data.data[0].devices;this.topoLinks = res.data.data[0].relation;for (let item of this.topoNodes) {item.symbol = require(`@/assets/images/${item.type}.svg`);}for (let item of this.topoLinks) {item.source = Number(item.source);item.target = Number(item.target);}//console.log('初始数据',this.topoNodes)}}).catch(() => {this.$message.error("获取失败");});},//移动事件moveAndLink(index, e) {// 判断当前模式if (this.isMove) {// 移动模式const layerX = e.layerX - this.topoNodes[index].x;const layerY = e.layerY - this.topoNodes[index].y;//实时获取更新后的坐标document.onmousemove = (e) => {this.topoNodes[index].x = e.layerX - layerX;this.topoNodes[index].y = e.layerY - layerY;}//将新坐标存进数据库//如果使用模拟数据,删除该方法document.onmouseup = () => {this.positions = [];for (let j = 0; j < this.topoNodes.length; j++) {this.positions.push({'ip': this.topoNodes[j].ip,'x': this.topoNodes[j].x,'y': this.topoNodes[j].y})}this.$axios({url: window.config.Login_URL + "/mirror/spaces/topology",method: "POST",headers: {MyToken: this.token,},data: {positions: this.positions,},}).then(() => {}).catch(() => {});document.onmousemove = nulldocument.onmouseup = null}} else {document.onmousemove = null // 重置鼠标移动事件this.isMove = true // 重置为移动模式}},// 放大缩小zooming(){var svg = this.$d3.select('#svg');var zoom = this.$d3.zoom().scaleExtent([0.4, 5]).on("zoom", function (e) {svg.selectAll('g').attr('transform',e.transform);svg.selectAll('line').attr('transform',e.transform)});svg.call(zoom)}}}</script>

CSS

<style scoped>.content {width: 100%;display: flex;justify-content: center;align-items: center;}.topo {width: 1070px;height: 600px;}</style>

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。