基於 HTML5 Canvas 繪制的電信網絡拓撲圖


電信網結構(telecommunication network structure)是指電信網各種網路單元按技術要求和經濟原則進行組合配置的組合邏輯和配置形式。組合邏輯描述網路功能的體系結構,配置形式描述網路單元的鄰接關系,即以交換中心(或節點)和傳輸鏈路所組成的拓撲結構。常見的網絡拓撲結構有星型結構、總線結構、環形結構、樹形結構、網狀結構、混合型拓撲以及蜂窩拓撲結構等,本文的例子主要描繪的是總線型拓撲,在顯示上相對其他的結構類型來說更清晰明了,繪制起來也非常容易。

雖然題目起的名字是電信網絡拓撲圖,幾乎所有的拓撲圖都能涵蓋,例如基本網絡圖,網絡拓撲圖,機架圖,網絡通信圖,3D網絡圖等等。

效果圖如下:

這個圖看起來挺簡單的,代碼也少,但是內容不少。

首先,機櫃01、機櫃02、機櫃03 都是 ht.Group “組”類型,ht.Group 類型用於作為父容器包含孩子圖元,在 GraphView 拓撲圖(http://www.hightopo.com)上可通過雙擊進行展開合並,合並時會自定隱藏子孫圖元節點, 如果有子節點有連線連接到外部時,合並的 Group 將代理進行連接。Group 的移動會帶動孩子節點跟隨, 孩子的位置和大小變化也會影響 Group 的展開圖形和 position 位置。

這邊提到一個代理連線的問題,“代理”兩個字可以很好地表明代理連線意義。實際上就是如果組內部的節點與組外部的節點有連線,那么在組合並的時候,會在這個組會“代理”與外部節點之間的連線,這個就是代理連線。我們拿機櫃02來說吧,機櫃02內部有一個“電腦”與“內部網絡交換機”之間有兩條連線,那么當我們雙擊機櫃02合並時,實際上就相當於機櫃02與“內部網絡交換機”之間有兩條連線了。

那么,我們來看看如何繪制這個組以及組內部的節點吧,先創建“機櫃02”的 Group 節點,因為整個例子我創建了三個 Group 節點,而且創建的方式都類似,因此把創建組的代碼封裝起來復用:

function createGroup(name, x, y) {
    var group = new ht.Group();//組類型 實際上也是一個節點
    group.setExpanded(true);//設置展開組
    group.setName(name);//設置組的名字
    group.s({//設置組的樣式style
        'group.title.background': 'rgba(14,36,117,0.80)',//組展開后的title背景顏色,僅對group.type為空的類型起作用
        'group.background': 'rgba(14,36,117,0.40)',//組展開后的背景顏色
        'group.title.align': 'center'//組展開后的title文字水平對齊方式,默認值為'left',可設置為center和right
    });
    group.setPosition(x, y);//設置組的位置
    group.setImage('images/服務器.json');//設置拓撲上展現的圖片信息,在GraphView拓撲圖中圖片一般以position為中心繪制
    dataModel.add(group);//將創建的組節點添加進數據容器中

    return group;
}

組是可以通過雙擊展開合並的,展開的時候顯示的是一個有標題欄的框(當然這些都是可以自定義的),合並的時候就顯示上面代碼中設置的 group.setImage 中的圖片。

所有機櫃內部的節點都是 ht.Node 類型的節點,所以我也封裝了一下:

function createNode(image, parent, x, y) {
    var node = new ht.Node();//創建一個 Node 節點
    if (image) node.setImage(image);//設置節點的顯示圖片
    if (parent) node.setParent(parent);//設置節點的父親
    if (x && y) node.setPosition(x, y);//設置節點的位置
    dataModel.add(node);//將節點添加進數據容器中

    return node;
}

生成機櫃02:

cabinet = createGroup('機櫃02', 146, 445);//創建機櫃02
createNode('images/正常.json', cabinet, 78, 440).s('label', '數據監控分析系統');//創建帶有“正常”圖片的節點,並設置這個節點的文字為“數據監控分析系統”

因為連線需要的是“源節點”以及“終節點”,這邊源節點是中間的“內部網絡交換機”,我們再創建這個節點:

var line = createNode();//創建一個節點
line.setSize(725, 20);//設置節點大小
line.setPosition(310, 325);//設置節點位置
line.s({//設置節點的style屬性
    'shape': 'roundRect',//決定shape的形狀,默認值為空,代表用image繪制。roundRect四周圓角矩形
    'shape.background': 'rgba(14,36,117,0.80)',//背景填充顏色,為null代表不填充背景
    'shape.border.color': '#979797',//邊框顏色
    'shape.corner.radius': 10,//該參數指定roundRect類型的圓角半徑,默認為空系統自動調節,可設置正數值
    'label': '內部網絡交換機', //文字內容,默認為空
    'label.position': 45,//文字內容,默認為空
    'label.offset.x': 50,//文字水平偏移,對於Edge意味着沿着連線方向水平偏移
    'label2': '內部網絡交換機',//HT默認除了label.*的屬性外,還提供了label2.*的屬性,用於滿足一個圖元需要顯示雙文字的情況
    'label2.position': 48,
    'label2.offset.x': 50,
    'label2.offset.y': 2,
});

不知道你們有沒有注意到,有一個 label2 的樣式屬性,這個是 HT 為了能在一個節點上添加兩個 label 文本而增加的功能,label 屬性和 label2 的屬性是完全相同的,只要在設置屬性的時候用 label 和 label2 區分開來就可以。

源節點和終節點都具備了,可以制作連線了:

createEdge(line, createNode('images/電腦.json', cabinet, 185, 450), 'rgb(30,232,178)', -100, true);
//參數1 源節點,參數2 終節點,參數3 連線顏色,參數4 連線起始點的水平偏移,參數5 是否創建兩條連線

還有一點有趣的,“交換機”的部分,最左側藍色方形的節點和中間長條的節點並不是一體的,而是分離的,但是我通過 setHost 進行節點與節點間的吸附,然后反吸附回來,這樣操作上就相當於這兩個節點是一體的:

var exchange = createNode('images/交換機.json', null, -53, 313);
exchange.setHost(line);//設置吸附
line.setHost(exchange);//反吸附 又設置line的吸附為exchange

因為 HT 會按照節點添加進數據容器中的順序來進行層次的排列,我的交換機是在 line 的添加之后的,所以默認交換機的節點會顯示在 line 之下,我們將默認的層級顯示關閉,並設置交換機 exchange 顯示在數據容器的頂部:

dataModel.setAutoAdjustIndex(false);//將自動調整data在容器中索引順序的開關關閉
dataModel.sendToTop(exchange);//將data在拓撲上置頂

 代碼就是這些,還有不懂的可以留言或者私信我也可以,大家一起探討。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM