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

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

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

效果圖以下:服務器

591709-20180129182919390-1438018385.gif

這個圖看起來挺簡單的,代碼也少,可是內容很多。網絡

首先,機櫃0一、機櫃0二、機櫃03 都是 ht.Group 「組」類型,ht.Group 類型用於做爲父容器包含孩子圖元,在 GraphView 拓撲圖(http://www.hightopo.com)上可經過雙擊進行展開合併,合併時會自定隱藏子孫圖元節點, 若是有子節點有連線鏈接到外部時,合併的 Group 將代理進行鏈接。Group 的移動會帶動孩子節點跟隨, 孩子的位置和大小變化也會影響 Group 的展開圖形和 position 位置。spa

這邊提到一個代理連線的問題,「代理」兩個字能夠很好地代表代理連線意義。實際上就是若是組內部的節點與組外部的節點有連線,那麼在組合並的時候,會在這個組會「代理」與外部節點之間的連線,這個就是代理連線。咱們拿機櫃02來講吧,機櫃02內部有一個「電腦」與「內部網絡交換機」之間有兩條連線,那麼當咱們雙擊機櫃02合併時,實際上就至關於機櫃02與「內部網絡交換機」之間有兩條連線了。代理

那麼,咱們來看看如何繪製這個組以及組內部的節點吧,先建立「機櫃02」的 Group 節點,由於整個例子我建立了三個 Group 節點,並且建立的方式都相似,所以把建立組的代碼封裝起來複用:code

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:get

圖片描述

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在拓撲上置頂

代碼解釋就是這些。還有不懂的能夠留言或者私信我也能夠,你們能夠一塊兒探討。

相關文章
相關標籤/搜索