• JS实现网络拓扑图


    废话先不多说,先上图;这是一个模拟设备状态的拓扑图;图中节点右上角的圆形图标绿色代表正常,红色代表设备一次;在图片的左上角 是用来获取节点的详细信息的。具体方法在js中有注释,
    因为这只是个教程,所以在写代码上不是很规范。所以希望大家多多见谅。而且因为本人对这个插件的研究也有限,有什么不对的也希望多多交流 谢谢!
    接着上代码。这是前端html和js代码;首先介绍下该功能的实现方法。是利用GoJS插件。 网址http://gojs.net/latest/index.html其中官网的包可以在这里下载:http://gojs.net/latest/doc/download.html;官网提供的包是英文的包括注释也是,而且不是很详细。所有我在本例子中  将关键的代码全部做了注释。基本上有点基础应该都能弄明白;为了直观,我直接将代码注释写在了代码所在的位置;这个插件在官网提供了很多例子。也有APS文档。但是本人觉得他的API文档写的有点杂。很难看懂,跟别说那些英语基础不好的人了。但是没关系,后面我会介绍一下如何巧妙不看文档也能做出不同效果的拓扑图;或者说实现你想要的拓扑图;
      1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
      2 
      3 <html>
      4 <head>
      5     <title>安防点位拓扑图</title>
      6     <!-- /* Copyright ?1998-2013 by Northwoods Software Corporation. */ -->
      7     <link href="goSamples.css" rel="stylesheet" type="text/css" />
      8     <script type="text/javascript" src="go.js"></script>
      9     <!--    <script type="text/javascript" src="goSamples.js"></script>-->
     10     <script src="../resources/scripts/jquery-1.7.1.min.js" type="text/javascript"></script>
     11     <script type="text/javascript">
     12     var AjaxRequestBack=false;
     13     var IdList;
     14        function init() {
     15             if (window.goSamples) goSamples();  
     16             var $ = go.GraphObject.make;  
     17 
     18             myDiagram = $(go.Diagram, "myDiagram",
     19           {
     20               initialContentAlignment: go.Spot.Center //整个拓扑图的位置
     21           });
     22           //节点的图片,根据传进来的参数获取相对应的图片
     23             function nodeTypeImage(type) {
     24                 if (type.charAt(0) === "1") return "images/1.png";
     25                 if (type.charAt(0) === "2") return "images/2.png";
     26                 if (type.charAt(0) === "3") return "images/3.png";
     27                 if (type.charAt(0) === "4") return "images/4.png";
     28                 if (type.charAt(0) === "5") return "images/5.png";
     29                 if (type.charAt(0) === "6") return "images/6.png";
     30                 if (type.charAt(0) === "7") return "images/7.png";
     31                 if (type.charAt(0) === "8") return "images/8.png";
     32                 return "images/0.png";
     33             }
     34 
     35             function nodeProblemConverter(msg) {
     36                 if (msg) return "red";
     37                 return null;
     38             }
     39             //判断节点左边形状
     40             function nodeOperationConverter(s) {
     41                 if (s >= 2) return "TriangleDown";
     42                 if (s >= 1) return "Rectangle";
     43                 return "Circle";
     44             }
     45             //判断节点右边形状的颜色
     46             function nodeStatusConverter(s) {
     47                 if (s >= 2) return "red";
     48                 if (s >= 1) return "green";
     49                 return "green";
     50             }
     51             //可以通过 problem控制节点的连线和边框的颜色
     52             //data.status = 10.1;//控制节点内部图标的颜色
     53             //data.operation //控制节点内图标的形状
     54             myDiagram.nodeTemplate =
     55             $(go.Node, "Vertical",
     56                     { selectable: false,//是否可以选择节点并移动
     57                         mouseOver: function (e, obj) {//鼠标进入响应的事件方法
     58                            nodeDoubleClick(e, obj) //事件调用方法
     59                        }
     60                     },
     61             //         { doubleClick: nodeDoubleClick },//鼠标双击事件函数
     62             //{click: nodeDoubleClick }, //鼠标单击事件函数
     63           {locationObjectName: "ICON" },
     64             // new go.Binding("location", "loc", go.Point.parse).makeTwoWay(go.Point.stringify), //这里使用节点的位置参数,也可以不知用,不使用的时候,就的使用插件的布局属性
     65           $(go.Panel, "Spot",
     66             $(go.Panel, "Auto",
     67               { name: "ICON" }, //这个参数无所谓
     68               $(go.Shape,
     69                 { fill: null, portId: "", 
     70                 strokeWidth: 0,stroke: null },//这两个属性和起来去掉边框
     71                 new go.Binding("background", "problem", nodeProblemConverter)), //这里使用节点的问题描述 problem值为空时:控制线条和边框的颜色,即设备是否出现问题
     72               $(go.Picture,
     73               //{ stroke: ""},
     74                 { margin: 0 }, //这里控制图片和外围边框的边距
     75                 { desiredSize: new go.Size(60, 60) },
     76                 new go.Binding("source", "type", nodeTypeImage))), //这里是用节点的类型,即是用的图片
     77             //这段代码是控制节点内部左边图标初始颜色 形状等,位子信息
     78             //            $(go.Shape, "Circle",
     79             //              { alignment: go.Spot.TopLeft, alignmentFocus: go.Spot.TopLeft, //TopLeft显示的位置
     80             //                   10, height: 10, fill: "Green"//这里的颜色是控制节点内部左边图标的颜色
     81             //              },
     82 
     83             //              new go.Binding("figure", "operation", nodeOperationConverter)) //这里是用节点形状参数
     84 
     85             //这段代码是控制节点内部右边图标初始颜色 形状等,位子信息
     86             $(go.Shape, "Circle",
     87               { alignment: go.Spot.TopRight, alignmentFocus: go.Spot.TopRight, //TopLeft显示的位置
     88                    15, height: 15, fill: "Green"
     89               },
     90               new go.Binding("fill", "status", nodeStatusConverter)) //这里是用节点状态参数
     91               ),
     92               //这里是节点文字的样式
     93           $(go.TextBlock,
     94            { font: "bold 7px Helvetica, bold Arial, sans-serif",
     95               stroke: "black", margin: 3 },
     96             new go.Binding("text")));
     97 
     98             //设置线条的颜色
     99             function linkProblemConverter(msg) {
    100                 if (msg) return "red";
    101                 return "#ccc";
    102             }
    103 
    104 
    105 
    106             myDiagram.linkTemplate =
    107         $(go.Link, go.Link.AvoidsNodes,
    108           { corner: 3 }, //控制线的转弯的弧度值越小 越呈现直角
    109           $(go.Shape,
    110             { strokeWidth: 1 }, //控制线条的粗细,值越大  线越粗
    111             new go.Binding("stroke", "problem", linkProblemConverter)));
    112 
    113             //节点的布局                
    114             myDiagram.layout = $(go.LayeredDigraphLayout,
    115                         { direction: 270, //拓扑图的方向
    116                             layerSpacing: 10,
    117                             columnSpacing: 15,
    118                             setsPortSpots: false
    119                         });
    120 
    121 
    122             //在这里加载数据
    123             load();
    124             //利用随机数随机设备出现问题的方法
    125             function randomProblems() {
    126             if(AjaxRequestBack)
    127             {
    128                
    129             
    130                 var model = myDiagram.model;
    131                 //nodeDataArray
    132                 //设置问题节的颜色
    133                 var arr = model.nodeDataArray;
    134                 for (var i = 0; i < arr.length; i++) {
    135                     data = arr[i];
    136 
    137                     //console.log(data.key);
    138                     for(var t=0;t<IdList.length;t++)
    139                     {
    140                     if(data.key==IdList[t])
    141                     {
    142                          data.status = 3;
    143                     }
    144                     else{
    145                     //data.status = 1;
    146                     }
    147                     }
    148 
    149                     //data.problem = (Math.random() < 0.8) ? "" : "Power loss due to ...";//0.8是一个零界点
    150                     //data.problem = ""; //当为空的时候就是没问题
    151                     //data.problem = "Power loss due to ...";//当这个的时候就是有问题
    152                     //data.status = 10.1;//这个数据是用于判断节点右边正方形 圆形 三角形还有形状的颜色(右边形状不变)
    153                     //data.operation = 0.1; //设置节点左边正方形 圆形 三角形还有形状的颜色(左边的形状颜色不变)
    154                   
    155                     //data.operation = 0.3;
    156                     model.updateTargetBindings(data);
    157                      data.status = 1;
    158                 }  
    159            
    160 
    161                 //获取JSON数据中的linkDataArray
    162                 //设置节点之间线的颜色
    163                 /*
    164                 arr = model.linkDataArray;
    165                 for (i = 0; i < arr.length; i++) {
    166                     data = arr[i];
    167                     data.problem = (0.1 < 0.7) ? "" : "No Power";
    168                     model.updateTargetBindings(data);
    169                 }
    170                 */
    171                 AjaxRequestBack=false;
    172                 }
    173             }
    174             //设置间隔时间获取设备的状态
    175             function loop1()
    176             {
    177               setTimeout(function () { GetStatus(); loop1(); }, 4000);
    178             }
    179             loop1();
    180             function loop() {
    181                 setTimeout(function () { randomProblems(); loop(); }, 5500);
    182             }
    183             loop();  // start the simulation
    184             myDiagram.makeImage({
    185                 scale: 1,
    186                 background: "AntiqueWhite",
    187                 type: "image/jpeg",
    188                 details: 0.05
    189             });
    190         }
    191         function load() {
    192             var str = <%=Result%>;
    193             myDiagram.model = go.Model.fromJson(str);
    194 
    195             var arr = myDiagram.model.nodeDataArray;
    196             for (var i = 0; i < arr.length; i++) {
    197                 // alert(arr[i].text);
    198             }
    199 
    200 
    201         }
    202 
    203         function GetStatus() {       
    204             $.ajax({
    205                 url: 'GetEleStatus.ashx',
    206                 type:'post',
    207                 success: function (data) {
    208                     var result = eval("(" + data + ")");
    209                     IdList = result.IdList;
    210                   
    211                     AjaxRequestBack=true;
    212                 }
    213             });
    214 
    215         }
    216 
    217         function highlightNode(e, node) {
    218             alert(node.data.text);
    219         }
    220 
    221         function nodeDoubleClick(e, node) {
    222             $("#Loading").html("正在加载...");
    223             $.ajax({
    224                 url: 'GetElementInfo.ashx',
    225                 data: { "ElementID": node.data.key },
    226                 success: function (data) {
    227                     if (data != "false") {
    228                         data = eval("(" + data + ")");
    229                         var name = data.name;
    230                         var commont = data.commont;
    231 
    232                        $("#Info").html("<span>点位名称:"+name+"</span></br><span>点位描述:"+commont+"</span>")
    233                       
    234                     $("#Info").show();;
    235                     tag=true;
    236 
    237                     }
    238                 }
    239             });
    240         }
    241 
    242     </script>
    243 </head>
    244 <body onload="init()">
    245     <div id='Info' style="position: fixed; padding-top: 5px; margin: 1px; line-height: 20px;
    246         border-radius: 3px; background-color: #FFC435;  150px; height: 50px; z-index: 999;
    247         border: 1px solid #ccc; top: 7px; left: 7px;">
    248         <div id="Loading" style="text-align: center;  150px; margin-top: 15px;">
    249             选择点位</div>
    250     </div>
    251  
    252     <div id="myDiagram" style="border: solid 0px black;  100%; height: 900px;">
    253     </div>
    254 
    255     <br />
    256     <%--</div>--%>
    257 </body>
    258 </html>
    View Code
    接下来是后台代码;后台代码的注释也写在代码所在的行了。
      1 using System;
      2 using System.Collections.Generic;
      3 using System.Linq;
      4 using System.Web;
      5 using System.Web.UI;
      6 using System.Web.UI.WebControls;
      7 using System.Text;
      8 using System.Data;
      9 
     10 namespace Maticsoft.Web.test
     11 {
     12     public partial class DrowNode : System.Web.UI.Page
     13     {
     14       
     15         public string Result;
     16         protected void Page_Load(object sender, EventArgs e)
     17         {
     18             DataSet set = new DataSet();
     19             set = new Maticsoft.BLL.RD_Element().Query("");//这里是写的SQL语句 去获取你数据库的数据。这里我删除掉了。而是利用下面构造的数据。这里你获取的数据必须包含两个字段,一个是父节点编号,一个是子节点编号。
     20             if (set != null && set.Tables.Count > 0)
     21             {
     22 
     23                 StringBuilder result = new StringBuilder();
     24                 StringBuilder node = new StringBuilder();//这个对象是存放着节点信息
     25                 StringBuilder link = new StringBuilder();//这个节点是存放每个节点的关联关系
     26                
     27                 //这两个是节点的位置。但是我用了另一种布局方式,这里已经没用了。
     28                 int y = 0;
     29                 int x = 0;
     30                 Random r = new Random();
     31                 int count = set.Tables[0].Rows.Count;
     32                 // 下面是构造的数据。该插件是利用后台生成的Json格式数据来解析的;
     33                 //key 是节点编号 text是节点下面的文字。type是节点的类型。在html代码有一个方法nodeTypeImage就是根据这个来返回图片路径的。problem则是用来标识节点数否异常。这里有一个可能会混淆,那就是节点异常和节点之间的连接异常。具体在js代码有注释,当然这里还有其他的属性,就不一一介绍了。
     34                 node.Append("{"key":"0", "text":"北京", "type":"0", "problem":""},");
     35                 node.Append("{"key":"-1", "text":"中国", "type":"0", "problem":""},");
     36                 node.Append("{"key":"-2", "text":"福建", "type":"0", "problem":""},");
     37                 node.Append("{"key":"10000", "text":"风扇", "type":"2", "problem":""},");
     38                 node.Append("{"key":"10001", "text":"风扇风扇", "type":"2", "problem":""},");
     39                 node.Append("{"key":"10002", "text":"风扇", "type":"4", "problem":""},");
     40                 node.Append("{"key":"10003", "text":"风扇", "type":"5", "problem":""},");
     41                 node.Append("{"key":"10004", "text":"发电机", "type":"1", "problem":""},");
     42                 node.Append("{"key":"10005", "text":"水龙头", "type":"5", "problem":""},");
     43                 node.Append("{"key":"10006", "text":"发电站", "type":"7", "problem":""},");
     44                 node.Append("{"key":"10007", "text":"火箭", "type":"8", "problem":""},");
     45                 node.Append("{"key":"10008", "text":"卫星", "type":"3", "problem":""},");
     46                 node.Append("{"key":"10009", "text":"卫星", "type":"5", "problem":""},");
     47                 node.Append("{"key":"100010", "text":"卫星", "type":"6", "problem":""},");
     48                 node.Append("{"key":"100011", "text":"火箭", "type":"3", "problem":""},");
     49                 node.Append("{"key":"100012", "text":"发电机", "type":"3", "problem":""},");
     50                 node.Append("{"key":"100013", "text":"发电机", "type":"5", "problem":""},");
     51                 node.Append("{"key":"100014", "text":"风扇", "type":"6", "problem":""},");
     52                 node.Append("{"key":"100015", "text":"拖拉机", "type":"3", "problem":""},");
     53                 node.Append("{"key":"100016", "text":"公交车", "type":"5", "problem":""},");
     54                 node.Append("{"key":"100017", "text":"广场控灯", "type":"6", "problem":""},");
     55                 node.Append("{"key":"100018", "text":"演出屏幕", "type":"3", "problem":""},");
     56                 node.Append("{"key":"100019", "text":"话筒", "type":"3", "problem":""},");
     57                 node.Append("{"key":"100020", "text":"音箱", "type":"5", "problem":""},");
     58                 node.Append("{"key":"100021", "text":"核武器", "type":"6", "problem":""},");
     59                 //这里的数据是关联各个节点的。from是线出来的节点编号,to则是连线到达的节点编号。这样就能把两节点关联起来
     60                 link.Append("{"from":"0", "to":"-1","problem":""},");
     61                 link.Append("{"from":"-2", "to":"-1","problem":""},");
     62                 link.Append("{"from":"10000", "to":"0","problem":""},");
     63                 link.Append("{"from":"10001", "to":"0","problem":""},");
     64                 link.Append("{"from":"10002", "to":"0","problem":""},");
     65                 link.Append("{"from":"10003", "to":"10002","problem":""},");
     66                 link.Append("{"from":"10004", "to":"10002","problem":""},");
     67                 link.Append("{"from":"10005", "to":"-2","problem":""},");
     68                 link.Append("{"from":"10006", "to":"-2","problem":""},");
     69                 link.Append("{"from":"10007", "to":"-2","problem":""},");
     70                 link.Append("{"from":"10008", "to":"100017","problem":""},");
     71                 link.Append("{"from":"10009", "to":"-2","problem":""},");
     72                 link.Append("{"from":"100010", "to":"-2","problem":""},");
     73                 link.Append("{"from":"100011", "to":"100019","problem":""},");
     74                 link.Append("{"from":"100012", "to":"10005","problem":""},");
     75                 link.Append("{"from":"100013", "to":"10005","problem":""},");
     76                 link.Append("{"from":"100014", "to":"10005","problem":""},");
     77                 link.Append("{"from":"100015", "to":"10007","problem":""},");
     78                 link.Append("{"from":"100016", "to":"10007","problem":""},");
     79                 link.Append("{"from":"100017", "to":"10009","problem":""},");
     80                 link.Append("{"from":"100018", "to":"10007","problem":""},");
     81                 link.Append("{"from":"100019", "to":"10009","problem":""},");
     82                 link.Append("{"from":"100020", "to":"100011","problem":""},");
     83                 link.Append("{"from":"100021", "to":"100011","problem":""},");
     84 
     85                 //这段代码是我本来用来构造数据库中数据的JSON格式的,但是因为没用了。不过来是贴出来,如果你有用可以照着这个写
     86                 //foreach (DataRow row in set.Tables[0].Rows)
     87                 //{
     88                 //    x = r.Next(count*20)+40;
     89                 //    y = r.Next(count*20)+100;
     90                 //    node.Append("{"key":"" + row["id"] + "", "text":"" + row["name"] + "", "type":"" + row["type"] + "", "loc":"" + x + " "+y+"","problem":""},");
     91 
     92                 //    //elemodel = new BLL.RD_Element().GetModel(int.Parse(row["parentid"].ToString ()));
     93                 //    link.Append("{"from":"" + row["id"] + "", "to":"" + row["parentid"].ToString() + "","problem":""},");
     94                 //}
     95                 string nodestr = node.ToString().Substring(0, node.ToString().Length - 1);
     96                 string linkstr = link.ToString().Substring(0, link.ToString().Length - 1);
     97 
     98 
     99                 result.Append("{"nodeDataArray": [ ");
    100                 result.Append(nodestr);
    101                 result.Append("],"linkDataArray": [ ");
    102                 result.Append(linkstr);
    103                 result.Append("]}");
    104                 Result = result.ToString();
    105             }
    106         }
    107         
    108     }
    109 }
    View Code

    然后是异步获取设备状态的C#代码。这里因为没有真正的设备信息。所以获取的异常设备都是利用随机函数构造出来的 代码如下 其中返回的是json格式的数据,数据为异常设备的编号

     1 using System;
     2 using System.Collections.Generic;
     3 using System.Linq;
     4 using System.Web;
     5 
     6 namespace Maticsoft.Web.test
     7 {
     8     /// <summary>
     9     /// GetEleStatus 的摘要说明
    10     /// </summary>
    11     public class GetEleStatus : IHttpHandler
    12     {
    13 
    14         public void ProcessRequest(HttpContext context)
    15         {
    16             context.Response.ContentType = "text/plain";
    17 
    18             string result="{"IdList":[";
    19           
    20             Random r = new Random();
    21             for (int i = 0; i < 10; i++)
    22             {
    23                 result += r.Next(100000,100022)+",";
    24             }
    25             result = result.Substring(0, result.Length - 1);
    26             result += "]}";
    27             context.Response.Write(result);
    28         }
    29 
    30         public bool IsReusable
    31         {
    32             get
    33             {
    34                 return false;
    35             }
    36         }
    37     }
    38 }
    View Code

    最后是获取设备的详细信息,这个是在鼠标移动到设备节点上的时候异步请求获取的。这里就不详细说了,大家可以根据自己的需求来做,也不难。

    然后做一下总结。插件首先是解析你构造的Json数据,然后放在myDiagram.model对象里。在数据中有两个数据:nodeDataArray和linkDataArray分别存放节点信息和节点关联信息;然后js去遍历迭代这是两个数组中的数据来构造拓扑图。那么在迭代的过程中。我们可以利用自己的需求去添加代码实现我们想要的拓扑图!

    这里的话我分享下我是这么做的吧。首先 如果你的英语水平很好并且文档阅读能力较强,那么可以不用往下看了。因为直接去看文档理解得也深一些,也能明白一些实现原理。

    首先 你的明白你的需求是什么。即你要实现什么样的拓扑图。然后 你去官网他的例子里面找。找到和你想要的差不多的拓扑图,或者某个拓扑图有你要的某个样式或者布局方式,或者交互方式等等。然后看他的代码。那么这里你有的先了解整个插件的实现过程。你可以通过详细分析我的代码和注释,应该就能大概明白某写代码是什么功能。某个功能是那个方法实现的,因为整个插件的实现原理都是一样的。所以一些方法和属性也是一样的,只不过根据属性的值,能得到不同的拓扑图;比如布局属性myDiagram.layout  比如节点连接属性:myDiagram.linkTemplate 那么这里就那布局属性说事,可能你想要的布局不是我这个例子中的样子,那么你就可以到其他拓扑图找到你想要的布局方式,然后把他的代码拿过来。替换掉现有的布局代码,当然这里布局有两种方式,一种是插件自动给你布局,就像我这个例子,还有一种是你自己构造每个节点的位置。 其他的也都大同小异。其实这就是一个组装拼接的过程。有时候一些外国插件没有什么文档的时候,我都是这干的,而且效果不错,速度也快。当然可能这样做对整个插件的理解就没有那么透彻了;

    (这里插播一条广告:http://xiamiwage.taobao.com/这是本人的淘宝店。唉 苦逼的挨踢男。希望大家多多支持吧)

    最后  因为这个插件是带有水印的。如果要去水印。就得到他的官网注册购买。当然我这也有一个破解版的,不过如果你真的要用,还是希望支持正版。

    下载地址如下:http://pan.baidu.com/share/link?shareid=203307637&uk=370619680

    最后 因为是第一次写博客,有什么需要改进的地方请多多批评 多多建议。谢谢,也希望多多交流。哈哈

    源码地址:https://files.cnblogs.com/zhijiang/DrowNode.rar

  • 相关阅读:
    sharepoint部署
    继承实体类出现传值时值不能保留
    面试经历
    sharepoint更换数据库链接
    asp.net c# 打开新页面或页面跳转
    sharepoint中配置工作流
    AD添加组织单位
    常用正则表达式
    删除多级非空目录
    C#实现对Word文件读写
  • 原文地址:https://www.cnblogs.com/zhijiang/p/3282057.html
Copyright © 2020-2023  润新知