數百個 HTML5 例子學習 HT 圖形元件 – 拓撲圖篇
HT 是啥:Everything you need to create cutting-edge 2D and 3D visualization.
這口號是當年心目中的產品方向,接著就朝這個方向慢慢打磨,如今 HT 算是達到了這樣的效果,談不上用盡洪荒之力,但我們對產品結果很滿意,特別是 HT 的使用者手冊,將例子和文件無縫融合一體,小小 10 來兆開發包居然包含了四十五份手冊,數百個活生生的 HTML5 例子,還沒體驗過的同學可以點選 http://www.hightopo.com/guide/readme.html HT 手冊入口玩一玩。
這樣綜合並可搜尋的手冊入口居然還常被問及 HT 的 Demo 在哪裡?只能怪這些年深入人心的極致使用者體驗理念,把人慣得包括很多程式設計師都如此之“懶”,當然也怪我們沒把使用者體驗的最後一公里做到位,於是最近 wangyinlong 同學人工例子抓圖,將數百個手冊例子進行了歸類整理,最終形成了方便大家直觀查詢所有 HT 例子的頁面:
很明顯 http://www.hightopo.com/demos/index.html 相比 http://www.hightopo.com/guide/readme.html 頁面,對於 HT 老使用者包括我們自己做技術支援,都感覺查詢例子更直觀方便,但對於 HT 初學者,面對這一堆數百個涵括通用元件、網路拓撲圖元件、3D 元件、向量圖形、各種編輯器等等五法八門的 HTML5 例子盛宴,往往無從下手,為此我打算寫個《數百個HTML5例子學習HT圖形元件》的系列文章,引導各種電力、電信、工控 SCADA 等不同行業領域使用者,學習使用 HT 這全套一站式 HTML5 圖形元件。
拓撲圖元件作為最典型的 HT 客戶需求應用,自然是首篇登場。
HT 的拓撲圖元件主要基於 HTML5 的 Canvas 技術,拓撲圖是電力和電信的叫法,但該元件遠不僅僅用於呈現節點和連線,在 HT 裡面我們沒把該元件狹義的稱為 Topology、Network 或 Diagram,我們將該元件類名稱為更通用的 GraphView,只要你有想象力,你可以用拓撲圖元件做出任何其他元件,對於一些需求你想不出來用啥元件實現時,往往就是拓撲圖元件需要站出來發力了:
可能大部分不在遊戲領域混的同學會好奇上面兩張圖是什麼鬼?這兩張是開源的 HTML5 遊戲引擎工具 QICI Engine (https://github.com/qiciengine/qiciengine
QICI Engine:A free JavaScript game engine library with a web-based comprehensive suite of toolset for making HTML5 games.
整個 QICI Engine 的 HTML5 遊戲引擎編輯工具就是基於 HT 元件定製開發出來的,上圖刀塔場景的資源管理器就是圖示可縮放,圖集可展開合併,可縮小變成樹層次的 GraphView 拓撲圖,而第二張的動作編輯器、曲線編輯器等等部分也都是 GraphView 的身影。
現在你應該能理解為什麼我說拓撲圖元件幾乎可作出任何其他元件,當然定製其他元件是需要時間精力成本的,否則也不需要有其他元件的存在意義了,開發 QICI Engine 產品是另一個故事,今天就先不展開了。HTML5 遊戲已經不是啥新鮮玩意兒了,但遊戲開發工具完全基於 HTML5 可執行在瀏覽器還是有點意思的,下圖附上阿明同學的得意之作《城市消消樂》抓圖,有興趣的可玩之:http://engine.zuoyouxi.com/game/Subara/index.php
// 建立資料模型容器
var dataModel = new ht.DataModel();
// 建立拓撲圖元件
var graphView = new ht.graph.GraphView(dataModel);
// 建立一個起始節點,設定名字和位置屬性,新增到資料模型容器
var source = new ht.Node();
source.setName('source');
source.setPosition(100, 70);
dataModel.add(source);
// 建立一個結束節點,設定名字和位置屬性,新增到資料模型容器
var target = new ht.Node();
target.setName('target');
target.setPosition(260, 70);
dataModel.add(target);
// 建立一條連線,設定起始和結束節點,新增到資料模型容器
var edge = new ht.Edge();
edge.setSource(source);
edge.setTarget(target);
dataModel.add(edge);
相信上面的程式碼很直觀就能理解拓撲圖構建的原理,很多人會問 HT 如何通訊獲取資料,對後端有限制嗎?HT 只是客戶端元件,不介入到後臺通訊,因此客戶可以採用任何後臺系統,Java、C++、PHP、Node.js 等等,可採用任何通訊方式 HTTP/AJAX、WebSocket 等,採用任何資料格式 XML、JSON 或 TXT 等,只需要最後使用者根據自己格式的資料內容,採用 HT 圖形庫提供的標準 API 介面建立相應的節點、連線等圖元,設定相關的屬性資訊,即可實現圖形呈現,所以 HT 元件對後臺和通訊方式沒有任何要求。
以上的例子對於名稱和位置的設定都是 demo 中隨意設定的值,真正的系統使用者一般會通過後臺數據庫查詢,然後根據業務資料內容構建圖元並設定相應的屬性。你會發現雖然在構建拓撲圖,但你80%的程式碼都在和 Data 和 DataModel 打交道,這兩個又是什麼鬼?其實絕大部分 HT 的客戶開發完整個系統都沒必要認真學習《HT for Web 資料模型手冊》,也不用管 HT 採用的是啥 MVC/MVP/MVVM 框架,需要深入瞭解的可閱讀 http://www.hightopo.com/guide/guide/core/datamodel/ht-datamodel-guide.html 手冊
簡單說 Data 就是 HT 的最小資料單元,對於 GraphView 元件可以說是一個圖元,一個節點或一條連線;對於 Tree 元件可以說是一個樹節點;對於 Table 元件可以說是一行記錄,這些 Data 圖元需要新增到 DataModel 的資料容器中,而 HT 的所有檢視元件 GraphView、List、Tree、Table 甚至是 3D 元件 Graph3dView 都會繫結一個數據容器,這些檢視都會監聽資料容器的事件變化,進行自身元件的重新整理顯示工作,這些事件包括圖元的屬性變化、圖元的增刪,還有很重要的一個關係,就是圖元的父子關係變化。
// 建立資料容器
dataModel = new ht.DataModel();
// 建立拓撲圖、屬性頁、列表、樹、表格、樹表元件
graphView = new ht.graph.GraphView(dataModel);
propertyView = new ht.widget.PropertyView(dataModel);
listView = new ht.widget.ListView(dataModel);
treeView = new ht.widget.TreeView(dataModel);
tablePane = new ht.widget.TablePane(dataModel);
treeTablePane = new ht.widget.TreeTablePane(dataModel);
// 建立組圖元,新增孩子節點,加入資料容器
group = new ht.Group();
group.setName('HT for Web ' + ht.Default.getVersion());
group.addChild(hello);
group.addChild(world);
group.addChild(edge);
dataModel.add(group);
這個例子增加了設定父子關係的程式碼,同時有更多的元件(拓撲圖、屬性頁、列表、樹、表格、樹表元件)綁定了同一個資料模型 DataModel,但使用者的程式碼依然主要在 Data 和 DataModel 上的操作,這也是 HT 架構設計的優勢,使用者使用更多元件並沒有增加新的學習成本,只要掌握的 DataModel 的基本操作,更多的元件也是如此。
graphView.addInteractorListener(function (e) {
if(e.kind === 'clickData'){
console.log(e.data + '被單擊');
}
else if(e.kind === 'doubleClickData'){
console.log(e.data + '被雙擊');
}
});
如果你還想打破砂鍋問到底為什麼不直接在 Data 或 DataModel 上提供互動處理,Data 資料是可以給很多 View 檢視共享用的,DataModel 甚至都不知道 View 檢視的存在,他們只會派發模型變化事件,而 View 通過監聽模型的變化進行相應的更新處理,HT 的模型架構上極其類似 Facebook React https://facebook.github.io/react/ 的 Flux 單向流設計理念:http://facebook.github.io/flux/docs/overview.html
HT 的 DataModel 相當於 Flux 中的 Store 模組,拓撲圖、樹和表格這些自然對應 View 模組,一般發起 Action 動作就是後臺資料變化,或者使用者手工輸入表格屬性值之類,但最終都不是直接修改 View,都是從 Data/DataModel/Store 發起修改,然後資料模型派發事件給所有 View,最後 View 根據不同事件做相應的處理。
剛才的例子我們提到了一個 Group 型別,這個型別圖元節點在 GraphView 上顯示成了組合效果,可雙擊展開合併,可跟隨著孩子節點的位置大小變化和自適應變動,除了 Node、Edge、Group 外,HT 還提供了 Shape、Polyline、Grid、SubGraph 等多種圖元型別,這些圖元型別都具是有針對性的展示效果,以滿足各種行業的基本圖元需求:http://www.hightopo.com/guide/guide/core/beginners/ht-beginners-guide.html#ref_datatype
另外 HT 的向量內建了 Chart 型別,向量內建的 Chart 不同於傳統獨立的 Chart 元件,傳統的 Chart 是獨立的檢視 DOM 元件,但 HT 的拓撲是 Cavans 方式繪製,因此沒法實現 Chart 元件和普通圖元的不同層次融合顯示,但向量的 Chart 型別倒是完美的實現了這樣的融合,很多工控應用的客戶會將向量 Chart 與拓撲圖元素融合一體,可參見《基於HT for Web的Web SCADA工控移動應用》http://www.hightopo.com/blog/402.html 一文中 HT 的 Web SCADA 應用案例
當然你也可以把 HT 與 百度 ECharts 進行整合,只要是 HTML 圖形元件就可以整合到 HT 的佈局容器中,可參考《ECharts整合HT for Web的網路拓撲圖應用》,此例子將 ECharts 整合 HT 拓撲圖做了告警統計的圖表呈現效果:
除了混合第三方圖形元件庫外,HT 圖撲還能嵌入 SVG 的圖片進行向量呈現,參見《繪製SVG內容到Canvas的HTML5應用》
構建出拓撲圖後很多人關係的是如何實現動畫,動畫從本質上來說就是在一定的時間點上驅動圖元的引數變化,例如大小、顏色、粗細包括可見不可見等來實現各種動畫效果,而 HT 本來所有圖元都是資料驅動,使用者隨時可以修改 Data 上的任何屬性,因此隨便起個定時器 windwo.setInterval 不斷改變圖元屬性值即可實現動畫效果,但為了方便客戶 HT 還提供了諸多方便函式和外掛。
HT 的拓撲圖的節點位置都是邏輯座標,並非 GIS 的地理資訊經緯度座標,但這並不妨礙 HT 的拓撲圖可以和百度地圖、GoogleMap、OpenLayers 等第三方 GIS 地圖引擎進行整合呈現,參見《百度地圖、ECharts整合HT for Web網路拓撲圖應用》,該文將 HT 拓撲圖、百度地圖、ECharts、HT 連線流動和麵板等外掛做了個綜合的呈現展示效果:http://www.hightopo.com/demo/blog_baidu_20150928/ht-baidu.html
拓撲圖做完呈現需求效果之後,常會有拓撲圖紙資料需要儲存的需求,這個很簡單,DataModel 內建將所有資料轉換成 JSON 的功能,非常方便使用者將拓撲圖內容進行匯入匯出工作,一般使用者會將 JSON 資料字串化並進行壓縮,然後存到後臺資料庫或檔案系統,執行時再進行載入匯入,這方面請參見《HT for Web 序列化手冊》,其實 HT 的可序列化功能並非為拓撲圖元件特殊設計,本質是整個 DataModel 資料層就可以序列化,所以意味著你可以儲存表格內容、樹層次關係包括 3D 場景。
另外 HT 的資料繫結功能是非常讚的特點,往往讓你意想不到的寥寥幾行程式碼即可實現很有趣的功能,例如下面這個例子,實現一個 Chart 圖元在拓撲圖中,使用者看看拖拽圖元實現餅圖旋轉,雙擊切換是否中空,只有寥寥十來行程式碼即可實現,我是想不到如何還能更簡單實現這樣的功能:http://www.hightopo.com/guide/guide/core/databinding/examples/example_piebinding.html
雖然 HT 的拓撲圖元件可以承載萬以上的拓撲圖元量,但如果這些拓撲圖元都通過手工佈局那是不可思議的工作量,因此 HT 為拓撲圖元件提供的多種自動佈局引擎演算法,例如彈力佈局、圓形佈局、星型佈局和層次佈局等多種樣式效果
拓撲圖篇就寫這些吧,HT 的拓撲圖元件還有非常多的功能,無法在一篇部落格中說透,我只能蜻蜓點水的提到大部分拓撲圖應用需要關注的功能點,HT 更多的 HTML5 拓撲圖功能留給大家去探索吧。