vue用vis插件如何實現(xiàn)網(wǎng)絡(luò)拓撲圖
更新時間:2022年10月09日 15:38:22 作者:十二點的洛杉磯
這篇文章主要介紹了vue用vis插件如何實現(xiàn)網(wǎng)絡(luò)拓撲圖,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
vis插件實現(xiàn)網(wǎng)絡(luò)拓撲圖
安裝引入vis
1.npm安裝vis
npm install vis
2.引入vis
import { DataSet, Network } from 'vis';
vis使用示例
methods:{ globalTrace () { // create an array with nodes var nodes = new DataSet([ {id: 1, label: 'Node 1'}, {id: 2, label: 'Node 2'}, {id: 3, label: 'Node 3'}, {id: 4, label: 'Node 4'}, {id: 5, label: 'Node 5'} ]); // create an array with edges var edges = new DataSet([ {from: 1, to: 3}, {from: 1, to: 2}, {from: 2, to: 4}, {from: 2, to: 5} ]); // create a network var container = document.querySelector('#global_trace_content'); // provide the data in the vis format var data = { nodes: nodes, edges: edges }; var options = { //節(jié)點樣式 nodes: { shape: "box",//設(shè)置節(jié)點node樣式為矩形 fixed:true,//節(jié)點node固定不可移動 font: { color: "white", //字體的顏色 size: 30 //顯示字體大小 }, scaling: { min: 16, max: 32 //縮放效果比例 }, }, //連接線的樣式 edges: { color: { color: "rgb(97, 168, 224)", highlight: "rgb(97, 168, 224)", hover: "green", inherit: "from", opacity: 1.0 }, font: { align: "top",//連接線文字位置 }, smooth: true, //是否顯示方向箭頭 arrows: {to : true },//箭頭指向from節(jié)點 }, layout: { //以分層方式定位節(jié)點 hierarchical: { direction: "LR",//分層排序方向 sortMethod: "directed",//分層排序方法 levelSeparation:400//不同級別之間的距離 }, }, interaction: { navigationButtons: true, // hover: true, //鼠標移過后加粗該節(jié)點和連接線 selectConnectedEdges: false, //選擇節(jié)點后是否顯示連接線 }, }; // initialize your network! this.network = new Network(container, data, options); this.network.on("click",e=> this.showDetail(e));//單擊事件 this.network.on("doubleClick",e=> this.enterService(e))//雙擊事件 }, }, mounted(){ this.globalTrace() }
vis官方文檔
vis.js網(wǎng)絡(luò)拓撲圖點擊折疊節(jié)點和展開節(jié)點
首先看一下效果圖
1.數(shù)據(jù)中要添加的屬性如下圖所示:
2.數(shù)據(jù)中添加入上圖屬性后,添加點擊事件即可,代碼如下:
//todo 雙擊時折疊和展開 network.on("doubleClick", function(params) {//雙擊事件 if (params.nodes.length != 0) {//確定為節(jié)點雙擊事件 var click_node_id = params.nodes[0]; remove_all_sub_nodes(click_node_id); } }); //todo 刪除下級所有節(jié)點 function remove_all_sub_nodes(node_id) { var sub_nodes = get_directly_sub_nodes(node_id); // console.log('sub_nodes',sub_nodes) if (sub_nodes.length == 0) {//當(dāng)前點擊的為葉子節(jié)點 //判斷是否有下級節(jié)點 // console.log('sub',allNodes[node_id - 1]['subids']); if (typeof (allNodes[node_id - 1]['subids']) != 'undefined') { $.each(allNodes[node_id - 1]['subids'], function(index, item) { // console.log('allNodes[item - 1]',allNodes[item - 1]) nodes.add(allNodes[item - 1]); edges.add({id: node_id + '_' + item, from: node_id, to: item}); }); } else { alert('當(dāng)前為葉子節(jié)點'); } } else { $.each(sub_nodes, function(index, item) { var sub_sub_nodes = get_directly_sub_nodes(item); if (sub_sub_nodes.length == 0) { nodes.remove({id: item}); edges.remove({id: node_id + '_' + item}); } else { remove_all_sub_nodes(item); } nodes.remove({id: item}); edges.remove({id: node_id + '_' + item}); }); } } //todo 獲取某節(jié)點直屬下級節(jié)點 function get_directly_sub_nodes(node_id) { var return_nodes = []; var connectedNodes = network.getConnectedNodes(node_id);//獲取所有連接節(jié)點 $.each(connectedNodes, function(index, item) { // console.log('allNodes',allNodes) if (item != allNodes[node_id - 1]['pid']) {//當(dāng)前節(jié)點的父節(jié)點 ,不操作 return_nodes.push(item); } }); return return_nodes; }
3.完整代碼如下:
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>vis.js</title> <link rel="stylesheet" rel="external nofollow" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous"> <script type="text/javascript" src="js/jquery-1.12.4.min.js"></script> <script type="text/javascript" src="https://unpkg.com/vis-network/standalone/umd/vis-network.min.js"></script> <!--<script type="text/javascript" src="js/vis-network.min.js"></script>--> <style type="text/css"> #mynetwork { width: 600px; height: 600px; border: 1px solid lightgray; } *{padding: 0;margin: 0;} .menu{ /*這個樣式不寫,右鍵彈框會一直顯示在畫布的左下角*/ position: absolute; background: rgba(3,3,3,0.6); border-radius: 5px; left: -99999px; top: -999999px; } .menu ul{list-style: none} .menu ul li{ padding: 5px 10px; color: #ffff; border-bottom: 1px solid #ffffff; font-size: 14px; cursor: pointer; list-style: none; } .menu ul li:hover{ color: #659bc5; } .menu ul li:last-child{ border-bottom: none; padding: 5px 10px 0 10px; } </style> </head> <body> <div id="mynetwork"></div> <!--菜單操作--> <div id="menuOperation" class="menu" style="display: none;"> <ul> <li><span class="glyphicon glyphicon-off" aria-hidden="true"></span> 下線</li> <li><span class="glyphicon glyphicon-road" aria-hidden="true"></span> 通行</li> </ul> </div> <!--節(jié)點懸停--> <div class="menu" id="divHoverNode" style="display: none;"> <!--<ul></ul>--> </div> <script type="text/javascript"> // 創(chuàng)建節(jié)點數(shù)據(jù)數(shù)組 var allNodes = [ {id: 1,name: "外部網(wǎng)絡(luò)",type: "Internet",ip:"1.1.1.1",port:"未知",pid:0,subids: [2]}, {id: 2,name: "交換機",type: "switch",ip:"192.168.30.125",mac:"48:de:3d:e2:49:a8",model:"H3C",uptime:"2020-09-03 10:50:50",port:"22",pid:1, subids: [3, 4, 5, 6]}, {id: 3,name: "交換機",type: "switch",ip:"192.168.1.8",mac:"cd:bd:3d:e2:55:55",model:"pf",uptime:"2020-09-03 10:50:50",port:"33",pid: 2,subids: [7, 8]}, {id:4,name: "計算機",type: "computer",ip:"192.168.1.8",mac:"dv:bd:fd:e2:df:fd",model:"pf",uptime:"2020-09-03 10:50:50",account:"xiaox",location:"xianm",port:"44",pid: 2}, {id:5,name: "路由器",type: "rooter",ip:"192.168.1.8",mac:"ds:bd:3d:e2:ds:55",model:"pf",uptime:"2020-09-03 10:50:50",account:"xiaox",location:"xianm",port:"55",pid: 2}, {id:6,name: "服務(wù)器",type: "service",ip:"192.168.1.8",mac:"vf:eq:dd:e2:55:55",model:"pf",uptime:"2020-09-03 10:50:50",account:"xiaox",location:"xianm",port:"66",pid:2}, {id:7,name: "打印機",type: "print",ip:"192.168.1.8",mac:"ss:bd:3d:ju:55:55",model:"pf",uptime:"2020-09-03 10:50:50",account:"xiaox",location:"xianm",port:"77",pid: 3}, {id:8,name: "手機",type: "phone",ip:"192.168.1.8",mac:"ju:ju:3d:e2:55:uy",model:"pf",uptime:"2020-09-03 10:50:50",account:"xiaox",location:"xianm",port:"88",pid:3} ]; // 創(chuàng)建邊數(shù)據(jù)數(shù)組 var allEdges = [ { id:"1_2",from: 1, to: 2 }, { id:"2_3",from: 2, to: 3 }, { id:"2_4",from: 2, to: 4 }, { id:"2_5",from: 2, to: 5 }, { id:"2_6",from: 2, to: 6 }, { id:"3_7",from: 3, to: 7 }, { id:"3_8",from: 3, to: 8 } ]; /** * 自定義圖片 */ for (var i = 0;i < allNodes.length;i++){ if (allNodes[i].type == 'Internet'){ allNodes[i].image = 'image/internet.png'; } if (allNodes[i].type == 'switch'){ allNodes[i].image = 'image/switch.png'; } if (allNodes[i].type == 'hub'){ allNodes[i].image = 'image/hub.png'; } if (allNodes[i].type == 'computer'){ allNodes[i].image = 'image/computer.png'; } if (allNodes[i].type == 'rooter'){ allNodes[i].image = 'image/rooter.png'; } if (allNodes[i].type == 'service'){ allNodes[i].image = 'image/service.png'; } if (allNodes[i].type == 'print'){ allNodes[i].image = 'image/print.png'; } if (allNodes[i].type == 'phone'){ allNodes[i].image = 'image/phone.png'; } } // 獲取容器 var container = document.getElementById('mynetwork'); // 創(chuàng)建節(jié)點對象 var nodes = new vis.DataSet(allNodes); // 創(chuàng)建連線對象 var edges = new vis.DataSet(allEdges); // 將數(shù)據(jù)賦值給vis 數(shù)據(jù)格式化器 var data = { nodes: nodes, edges: edges }; console.log('nodes',data.nodes); var options = { nodes:{ shape: 'image'//設(shè)置圖片 // image:"https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1599645215703&di=0cb23e74736a6a1222f35b822f5bf833&imgtype=0&src=http%3A%2F%2Fa1.att.hudong.com%2F05%2F00%2F01300000194285122188000535877.jpg" }, interaction:{ hover:true, hoverConnectedEdges: true }, layout: { //樹形 // hierarchical: {direction: 'UD', sortMethod: 'hubsize'} }, }; // 初始化關(guān)系圖 var network = new vis.Network(container, data, options); /** * 節(jié)點鼠標懸停(點擊)獲取到的信息 * 因為hoverNode事件官方文檔中給的信息懸停時只傳了id值,想在鼠標懸停的時候顯示該節(jié)點的信息拿不到值,所以遍歷節(jié)點,相等的時候return改節(jié)點的信息 * @param option-----鼠標懸停時取得的id * @returns {{flag, port, ip, name, ignore, id, type}|{flag, port, ip, name, ignore, model, id, type, mac, uptime}|{flag, port, ip, name, ignore, model, location, id, type, mac, account, uptime}|*} */ function getNode(option) { for (var i = 0;i < allNodes.length;i++){ if (option == allNodes[i].id){ // console.log('i',allNodes[i]); return allNodes[i]; } } } /** * 線懸停(點擊)時兩端節(jié)點的信息(與節(jié)點類似) * edges中加了id屬性,代表線條指向,懸停時通過edges--id與nodes--id對比,將兩端節(jié)點信息拼湊出來 * @param option----鼠標懸停在線上時取得的id * @returns {Array} */ function getEdge(option){ var linkId = option; var linkIdFirst = linkId.substring(0,1);//截取第一位 var linkIdLast = linkId.substring(linkId.length-1,linkId.length);//截取最后一位 var dataList = [];//存放線條兩邊的節(jié)點nodes數(shù)據(jù) for (var j =0;j<allNodes.length;j++){ if (linkIdFirst == allNodes[j].id || linkIdLast == allNodes[j].id){ dataList.push(allNodes[j]); } } return dataList; } //todo 懸停在節(jié)點上--顯示彈框 network.on('hoverNode',function(properties){ // console.log('懸停節(jié)點',properties); var hoveNodeList = getNode(properties.node); // console.log('hoveNodeList',hoveNodeList); var deviceType = hoveNodeList.type; var imgPathSrc = hoveNodeList.image; if (deviceType == "Internet" || deviceType == "hub"){ var $ul = "<ul>" +"<li><img src=' "+imgPathSrc+" ' width='30px' height='25px'><span> "+hoveNodeList.name+" </span> </li>" +"</ul>"; $("#divHoverNode").append($ul); } else if (deviceType == "switch"){ var $ul = "<ul>" +"<li><img src=' "+imgPathSrc+" ' width='30px' height='25px'><span> 設(shè)備類型: "+hoveNodeList.name+" </span> </li>" +"<li>IP:"+ hoveNodeList.ip+"</li>" +"<li>MAC:"+ hoveNodeList.mac+"</li>" +"<li>設(shè)備型號:"+ hoveNodeList.model+"</li>" +"</ul>"; $("#divHoverNode").append($ul); }else{ var $ul = "<ul>" +"<li><img src=' "+imgPathSrc+" ' width='30px' height='25px'><span> 設(shè)備類型:"+hoveNodeList.name+" </span> </li>" +"<li>IP:"+ hoveNodeList.ip+"</li>" +"<li>MAC:"+ hoveNodeList.mac+"</li>" +"<li>賬號:"+ hoveNodeList.account+"</li>" +"<li>所在位置:"+ hoveNodeList.location+"</li>" +"<li>最后登錄時間:"+ hoveNodeList.uptime+"</li>" +"</ul>"; $("#divHoverNode").append($ul); } $('#divHoverNode').css({ 'display': 'block', 'left': properties.event.offsetX + 15, 'top' : properties.event.offsetY + 15 }); $('#menuOperation').hide(); }); //todo 從節(jié)點移開---隱藏彈框 network.on('blurNode',function(){ $("#divHoverNode").hide(); $("#divHoverNode").empty();//移除之后清空div }); //todo 懸停在邊上--顯示彈框 network.on('hoverEdge',function(properties){ // console.log('懸停邊',properties); var hoveEdgeList = getEdge(properties.edge); // console.log('hoveEdgeList',hoveEdgeList); var $ul = "<ul>" +"<li>名稱:"+ hoveEdgeList[0].name+"->"+hoveEdgeList[1].name+"</li>" +"<li>端口號:"+ hoveEdgeList[0].ip+"->"+hoveEdgeList[1].ip+"</li>" +"</ul>"; $("#divHoverNode").append($ul); $('#divHoverNode').css({ 'display': 'block', 'left': properties.event.offsetX + 15, 'top' : properties.event.offsetY + 15 }); $('#menuOperation').hide(); }); //todo 從邊上移開---隱藏彈框 network.on('blurEdge',function(properties){ $("#divHoverNode").hide(); $("#divHoverNode").empty();//移除之后清空div }); //todo 點擊的判斷是否選中節(jié)點時候顯示隱藏 network.on('click',function(properties){ var clickNodeList = getNode(properties.nodes[0]); // console.log('clickNodeList',clickNodeList); if (typeof(clickNodeList) == "undefined") { $('#menuOperation').hide(); }else{ $('#menuOperation').css({ 'display': 'block', 'left': properties.event.center.x + 15, 'top' : properties.event.center.y + 15 }); $("#divHoverNode").hide(); } }); //todo 雙擊時折疊和展開 network.on("doubleClick", function(params) {//雙擊事件 if (params.nodes.length != 0) {//確定為節(jié)點雙擊事件 var click_node_id = params.nodes[0]; remove_all_sub_nodes(click_node_id); } }); //todo 刪除下級所有節(jié)點 function remove_all_sub_nodes(node_id) { var sub_nodes = get_directly_sub_nodes(node_id); // console.log('sub_nodes',sub_nodes) if (sub_nodes.length == 0) {//當(dāng)前點擊的為葉子節(jié)點 //判斷是否有下級節(jié)點 // console.log('sub',allNodes[node_id - 1]['subids']); if (typeof (allNodes[node_id - 1]['subids']) != 'undefined') { $.each(allNodes[node_id - 1]['subids'], function(index, item) { // console.log('allNodes[item - 1]',allNodes[item - 1]) nodes.add(allNodes[item - 1]); edges.add({id: node_id + '_' + item, from: node_id, to: item}); }); } else { alert('當(dāng)前為葉子節(jié)點'); } } else { $.each(sub_nodes, function(index, item) { var sub_sub_nodes = get_directly_sub_nodes(item); if (sub_sub_nodes.length == 0) { nodes.remove({id: item}); edges.remove({id: node_id + '_' + item}); } else { remove_all_sub_nodes(item); } nodes.remove({id: item}); edges.remove({id: node_id + '_' + item}); }); } } //todo 獲取某節(jié)點直屬下級節(jié)點 function get_directly_sub_nodes(node_id) { var return_nodes = []; var connectedNodes = network.getConnectedNodes(node_id);//獲取所有連接節(jié)點 $.each(connectedNodes, function(index, item) { // console.log('allNodes',allNodes) if (item != allNodes[node_id - 1]['pid']) {//當(dāng)前節(jié)點的父節(jié)點 ,不操作 return_nodes.push(item); } }); return return_nodes; } </script> </body>
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
詳解axios 全攻略之基本介紹與使用(GET 與 POST)
本篇文章主要介紹了axios 全攻略之基本介紹與使用(GET 與 POST),詳細的介紹了axios的安裝和使用,還有 GET 與 POST方法,有興趣的可以了解一下2017-09-09