天天看點

前端入門:快速開發基于 HTML5 網絡拓撲圖應用

計算機網絡的拓撲結構是引用拓撲學中研究與大小,形狀無關的點、線關系的方法。把網絡中的計算機和通信裝置抽象為一個點,把傳輸媒體抽象為一條線,由點和線組成的幾何圖形就是計算機網絡的拓撲結構。網絡的拓撲結構反映出網中各實體的結構關系,是建設計算機網絡的第一步,是實作各種網絡協定的基礎,它對網絡的性能,系統的可靠性與通信費用都有重大影響。拓撲在計算機網絡中即是指連接配接各結點的形式與方法;在網絡中的工作站和伺服器等網絡單元抽象為“點”;網絡中的電纜等抽象為“線”。影響網絡性能、系統可靠性、通信費用。

拓撲還分為:總線拓撲、星型拓撲、環形拓撲樹形拓撲以及網狀拓撲。這篇文章寫的案例就是總線拓撲中的一個分支,我們一步一步來搭建這個拓撲圖形。

示例圖檔:

前端入門:快速開發基于 HTML5 網絡拓撲圖應用

拓撲圖形元件 ht.graph.GraphView (以下簡稱 GarphView)是 HT 架構中 2D功能最豐富的元件,其相關類庫都在 ht.graph包下。 GarphView 具有基本圖形的呈現和編輯功能,拓撲節點連線及自動布局功能,電力和電信等行業預定義對象,具有動畫渲染等特效, 是以其應用面很廣泛,可作為監控領域的繪圖工具和人機界面,可作為一般性的圖形化編輯工具,可擴充成工作流群組織圖等企業應用。

HT 架構的元件指的是可視化可互動的視圖控件,HT 架構基于 HTML5 技術,是以

HT

元件的可視化部分本質就是 HTML 的元素, 大部分 HT 元件與 DataModel 資料模型綁定,使用者通過操作純 js 的語言即可驅動可視化元件,這樣屏蔽了 HTML 底層圖形技術複雜性。 HT 對 HTML5 技術封裝的目的在于提高開發效率和可維護性,但并不意味着不允許使用者直接操作 HTML 原生元素, 有 HTML5 開發經驗的程式員,在了解 HT 系統機制的前提下,大可運用各種 HTML5 的技術對 HT 元件做自定義擴充。

我們就是用 ht.graph.GraphView 元件作為場景的,具體代碼隻有兩行:

graphView = new ht.graph.GraphView();
graphView.addToDOM();      

首先聲明變量,然後将這個元件執行個體變量添加進 body 體中。所有 HT 元件最根層都為一個 div 元件,可通過元件的 getView() 函數獲得, 預設和自定義互動事件監聽一般添加在該 div 上(getView().addEventListener(type, func, false)), 渲染層一般由 canvas 提供。 使用者可直接對根 div 和 canvas 層設定css背景等樣式, 也可以添加新的 HTML 元件到根 div 層上,作為 canvas 的兄弟元件一起呈現。 HT 元件一般都以設定 position 為 absolute 的絕對定位方式。HT 的元件一般都會嵌入BorderPane、SplitView 和 TabView等容器中使用,而最外層的 HT 元件則需要使用者手工将 getView()傳回的底層 div 元素添加到頁面的 DOM元素中,這裡需要注意的是,當父容器大小變化時,如果父容器是 BorderPane和 SplitView 等這些 HT 預定義的容器元件,則 HT 的容器會自動遞歸調用孩子元件 invalidate函數通知更新。但如果父容器是原生的 html元素, 則 HT 元件無法獲知需要更新,是以最外層的 HT 元件一般需要監聽 window的視窗大小變化事件,調用最外層元件 invalidate函數進行更新。

為了最外層元件加載填充滿視窗的友善性,HT 的所有元件都有 addToDOM 函數,其實作邏輯如下,其中 iv 是 invalidate的簡寫:

addToDOM = function(){   
    var self = this,
        view = self.getView(),  //擷取底層 div 
        style = view.style;
    document.body.appendChild(view); //将元件底層 div 添加進 body 體中           
    style.left = \'0\';//ht 的元件預設将 position 設定為 absolute 絕對定位
    style.right = \'0\';
    style.top = \'0\';
    style.bottom = \'0\';      
    window.addEventListener(\'resize\', function () { self.iv(); }, false);            
}      

接下來我們要引入“資料容器”的概念,顧名思義,就是裝載資料的容器,資料容器 ht.DataModel(以下簡稱 DataModel)作為承載 Data 資料的模型,管理着 Data 資料的增删以及變化事件派發, HT 架構所有元件都是通過綁定 DataModel,以不同的形式呈現到使用者界面,可以通過 view.getDataModel() (簡寫為 view.dm())方式擷取資料容器;同時元件也會監聽 DataModel 模型的變化事件(view.getSelectionModel(),簡寫為 view.sm()), 實時同步更新界面資料資訊,掌握了 DataModel 的操作就掌握了所有元件的模型驅動方式。

我們要建立兩個節點 ht.Node(繼承于 ht.Data 類),一個伺服器,一個用戶端,中間連線兩條以及一條自環的連線,這些都是 Data 資料,都需要添加進 DataModel 資料容器中。但是我們得先建立這個資料節點,用 HT 隻需要兩句話就能将節點添加進資料容器中了,方法跟上面建立拓撲元件的方法很像,拓撲元件是添加進 body 體中,而節點是添加進資料容器中:

var server = new ht.Node();//建立“伺服器”資料節點
graphView.dm().add(server);//将節點添加進資料容器 graphView.dm() 中      

用戶端也是一樣的建立方式,節點名為 client。為了美觀,我給伺服器和用戶端的節點都設定了圖檔,設定圖檔有兩種方式:

  • 直接将圖檔相對或絕對路徑,設定到資料模型的相應屬性上,server.setImage(\'images/server.png\')
  • 先通過 ht.Default.setImage(\'server\', \'images/server.png\') 進行注冊,再将注冊名稱設定到模型上 server.setImage(\'server\')

直接設定路徑方式開發友善,無需提前注冊圖檔,但資料模型序列化時圖檔路徑占用記憶體較多,将來圖檔路徑變化後不利于管理維護,兩種方式都是正确的使用方式,可根據項目情況選中不同方式或混合使用。 如果采用 url 的路徑方式 HT 内部會自動加載圖檔,并在 onload 之後自動更新相應的視圖元件。

HT 的架構下圖檔被賦予了更廣泛的含義,

HT

提供了自定義 JSON 格式的矢量描述形式,以 HT 标準定義的 JSON 矢量格式, 也可以作為圖檔進行注冊和使用,HT 的矢量方式比傳統圖檔格式更節省空間,縮放不失真,最強大之處在于矢量的所有圖形參數, 皆可與 Data 模型上的資料動态綁定,具體說明參見矢量手冊,現在我這邊的講解還沒到這個步驟,感興趣的可以自行了解。

接着是建立兩個節點之間的連線,ht.Edge 類型用于連接配接起始和目标兩個 Node 節點,兩個節點間可以有多條 Edge 存在,也允許起始和目标為同一節點。為同一節點的情況就是形成自環的情況啦~這裡有三條連線,由于有兩條類似,我就隻将直線連線和自環的連線代碼貼出來進行解釋:

var edge = new ht.Edge(server, client);//建立連線節點,參數為起始節點和目标節點
graphView.dm().add(edge);//将連線節點添加進資料容器中

var cirEdge = new ht.Edge(server, server);//這個連線的起始節點和目标節點都為同一個節點,形成自環
graphView.dm().add(cirEdge);      

連線節點也繼承于 Data 類,是以添加進資料容器的方式也是一樣的。至于連線上面的字,則是通過 setStyle 方法來實作的。

HT 的資料 Data 可分為三種屬性類型:

  • get/set 或 is/set類型,例如 getName(0/setName(\'ht\') 和 isExpanded(),用于常用屬性操作
  • attr 類型,通過 getAttr(name)和 setAttr(key, value) 存取,該類型是 HT 預留給使用者存儲業務資料
  • style 類型,通過 getStyle(name)和 setStyle(key, value) 進行操作,GraphView 上圖元樣式由該類型屬性控制

這裡我是通過 style 類型來添加的文字說明,通過 ‘label’ 屬性設定顯示的文字:

edge.s({//setStyle 的簡寫
    \'label\': \'請求\',//設定文字
    \'label.position\': 3//設定文字位置
});      

最終顯示文字由 GraphView.getLabel 函數決定:

getLabel: function (data) {
    var label = data.getStyle(\'label\');//擷取 style 樣式中的 label 屬性的 value
    return label === undefined ? data.getName() : label; 
}      

上面還有一個文字位置,是 HT 封裝的位置,具體顯示位置如下:

前端入門:快速開發基于 HTML5 網絡拓撲圖應用

其中 17 為中心位置,大家可根據這個位置自行調整看看效果,位置的具體說明請參考 HT for Web 位置手冊。學習web前端:http://www.zhihaijiangku.com