基於 WebGL 的 3D 電信機架之資料繫結
前言
在前端中,檢視層和資料層需要進行單向或者雙向資料繫結,大家都已經不陌生了,有時候 2D 做的比較順了之後,就會想要挑戰一下 3D,不然總覺得癢癢的。這個 3D 機架的 Demo 我覺得非常有代表性,首先,3D 機架用途非常廣,尤其是在電信行業,就算不是機架,在比如工業方面 3D 模型以及資料繫結的應用也是非常廣泛的,畢竟現在工業物聯網已經是大趨勢了。
效果圖:
上面動圖中,閃爍燈是在不斷變化的,由於需要顯示的效果美觀一點,也實際一點,我截的圖還是比較完整的,但是這個閃爍的部分有點看不清楚(cnblog 中放太明顯的外鏈容易被移出首頁啊!!!等會再發!)。
程式碼實現
雖然上面 gif 圖中顯示的一個是 2D 的一個是 3D 的,但是構建的步驟以及需要的內容是一樣的,所以本文只針對 3D 的模型進行程式碼實現。
場景搭建
搭建一個 3D 場景是非常快速的,只需要三行程式碼:
dm = new ht.DataModel(); // 建立一個資料容器 資料容器也可以通過 g3d.getDataModel() 獲取
g3d = new ht.graph3d.Graph3dView(dm); // 建立一個 3D 場景,將資料容器作為引數傳遞進去,這樣資料容器中的內容就可以顯示在 3D 場景中了
g3d.addToDOM(); // 將 3D 場景新增到 body 體中
3D 機架模型構建
雖然可以叫設計師直接給我一個 obj 格式的模型,但是我覺得這個比較簡單,還是不要麻煩人家了。。。首先是建立一個六面體,模型上面的貼圖是我以前用的一個 json 格式的檔案,用來作為這個六面體的正面貼圖,這些部分都是寫在 json 檔案裡面的,我先擷取一小部分的 json 內容,然後用 js 程式碼復現:
{
"c": "ht.Node", // 一個 ht.Node 型別的元素
"i": 1277, // id
"p": { // 通過 set/get 來設定/獲取的元素的部分。如 setPosition/getPosition
"tag": "service", // 設定元素標籤 用來作為唯一標識
"image": "symbols/機櫃.json", // 設定節點圖片
"rotationX": 1.5708, // 設定節點 X 軸旋轉角度
"position": { // 設定節點位置
"x": 0,
"y": 225
},
"anchor": { // 設定節點錨點
"x": 0.5,
"y": 0.54
},
"anchorElevation": 1, // 設定節點 y 軸錨點
"width": 507, // 設定節點寬度
"height": 980, // 設定節點長度
"tall": 450, // 設定節點高度
"elevation": 451 // 控制 Node 圖元中心位置所在 3D 座標系的y軸位置
},
"s": { // 設定圖元的 style 樣式,HT 預定義的一些樣式屬性,通過 node.s('all.color') 獲取和設定節點的樣式
"all.color": "#DDDDDD", // 設定節點六面顏色
"top.image": "symbols/機櫃.json", // 設定節點頂部圖片
"front.visible": true, // 設定節點正面是否可見
"back.visible": true,
"left.visible": true,
"right.visible": true,
"bottom.visible": true
}
}
這部分的 json 內容大體上就是建立了一個 ht.Node 節點,然後對這個節點設定了一些屬性,包括節點座標,節點的大小,以及一些 style 樣式設定。
那麼,如何用程式碼來建立這樣一個節點呢?
var node = new ht.Node(); // 建立一個 ht.Node 型別的節點
node.setTag('service'); // 設定節點的標籤
node.setImage('symbols/機櫃.json'); // 設定節點圖片
node.setRotationX(Math.PI/2); // 設定節點 x 軸旋轉
node.setPosition(0, 225); // 設定節點位置
node.setAnchor(0.5, 0.54); // 設定節點錨點
node.setAnchorElevation(1); // 設定節點 y 軸方向的錨點
node.setWidth(507); // 設定節點的寬度
node.setHeight(980); // 設定節點的長度
node.Tall(450); // 設定節點的高度
node.setElevation(451); // 控制 Node 圖元中心位置所在 3D 座標系的 y 軸位置
node.s({ // 設定節點樣式
'all.color': '#ddd', // 六面顏色
'top.image': 'symbols/機櫃.json', // 節點頂部圖片
'front.visible': true, // 設定節點正面可見
'back.visible': true,
'left.visible': true,
'right.visible': true,
'bottom.visible': true
});
其實整個 json 就是由多個這種型別的圖元組合而成的。我們來拆析一下,整個 3D 機架實際上是由十個圖元組合而成的,第一個是整體的 3D 機櫃(也就是我們上面 json 內容中建立的部分),剩下的九個都是需要動態變化閃爍燈的裝置,也就是我紅框框起來的部分:
http://www.hightopo.com/demo/serviceShow/
這些裝置的建立方式跟上面的 3D 機架是類似的,只不過對應的節點尺寸小點,貼圖不一樣,座標不一樣罷了。但是下面的這九個節點的貼圖似乎有點不一樣?上面有閃爍的燈,並且不止一盞!怎麼動態獲取他們呢?
向量–資料繫結
不得不說到向量這個概念。向量在 HT for Web 中是向量圖形的簡稱,常見的 png 和 jpg 這類的柵格點陣圖, 通過儲存每個畫素的顏色資訊來描述圖形,這種方式的圖片在拉伸放大或縮小時會出現圖形模糊,線條變粗出現鋸齒等問題。 而向量圖片通過點、線和多邊形來描述圖形,因此在無限放大和縮小圖片的情況下依然能保持一致的精確度。
這些有點都是次要的,最重要的是這個向量可以進行資料繫結(這個資料繫結是繫結到節點中的),而且繫結方式非常容易!
向量採用 json 格式描述,使用方式和普通的柵格點陣圖一致,通過 node.setImage('hightopo.json')
或者 node.setIcon('hightopo.json')
等設定到資料模型中。
向量 json 描述必需包含 width、height 和 comps 引數資訊:
- width 向量圖形的寬度
- height 向量圖形的高度
- comps 向量圖形的元件 Array 陣列,每個陣列物件為一個獨立的元件型別,陣列的順序為元件繪製先後順序
由於這張圖繪製的還是比較複雜的,所以我就將設定了資料繫結的矩形部分的向量繪製程式碼貼上出來:
{
"width": 48, // 一個向量圖示必備的寬度 向量詳細內容請參考 HT for Web 向量手冊
"height": 262, // 一個向量圖示必備的高度
"comps": [ // 一個向量圖示必備的 Array 陣列元件
{ // 陣列元件中的第一個元素
"type": "rect", // 型別為矩形
"background": { // 設定矩形背景色
"func": "attr@rectBg1", // HT 用一個帶 func 屬性的物件替換以前的引數值 這裡就是進行資料繫結的地方
"value": "rgb(255,0,0)" // 如果 func 值為 undefined 或者 null 時,採用這個值
},
"shadow": true, // 設定“陰影”
"shadowColor": { // “陰影”顏色
"func": "attr@shadowColor1", // 這邊將“陰影”也進行了資料繫結,為的是能夠實現燈“發光”的效果
"value": "rgba(255,0,0,0.35)" // 設定備選值
},
"shadowOffsetX": 0, // 設定陰影橫軸偏移量
"shadowOffsetY": 0, // 設定陰影縱軸偏移量
"rect": [ // 設定該元件的寬高以及座標
4.38544, // x 軸座標
23.52679, // y 軸座標
14.46481, // width 元件寬度
6.1554 // height 元件高度
]
}
]
}
因為一個向量圖形中有 5 個“閃爍燈”,所以我新增了 5 個元件,也就是在 comps 引數裡面新增了五個元素,繫結的資料不同,為了省事,我將繫結的資料名都設定為“rectBg”後面加一個數字,這些數字依次遞增。
我們就是將這樣一張向量圖設定為節點的 front.image 作為節點正面顯示圖的:node.s('front.image', 'symbols/內部裝置2.json')
。
JSON 反序列化
會不會有人好奇 json 檔案裡面的內容是如何轉換成 3D 模型的?
說實在的,步驟依然很簡單:
ht.Default.xhrLoad('scene/service3d.json', function(text) { // xhrLoad 函式是一個非同步載入檔案的函式
dm.deserialize(text); // 反序列化資料容器,解析用於生成對應的 Data 物件並新增到資料容器 這裡相當於把 json 檔案中生成的 ht.Node 節點反序列化到資料容器中,這樣資料容器中就有這個節點了
});
由於 xhrLoad 函式是一個非同步載入函式,所以如果 dm 資料容器反序列化未完成就直接呼叫了其中的節點,那麼會造成資料獲取不到的結果,所以一般來說我是將一些邏輯程式碼寫在這個函式內部,或者給邏輯程式碼設定 timeout 錯開時間差。
首先,由於資料都是儲存在 dm 資料容器中的(通過 dm.add(node) 新增的),所以我們要獲取資料除了可以通過 id、tag 等獨立的方式,還可以通過遍歷資料容器來獲取多個元素:
var infos = [
{ shadowColor: 'shadowColor1', background: 'rectBg1' },
{ shadowColor: 'shadowColor2', background: 'rectBg2' },
{ shadowColor: 'shadowColor3', background: 'rectBg3' },
{ shadowColor: 'shadowColor4', background: 'rectBg4' },
{ shadowColor: 'shadowColor5', background: 'rectBg5' }
];
var len = infos.length; // 獲取陣列中的長度
var datas = dm.toDatas(function(d) { return d.getDisplayName() === 'device'; }); // 以過濾函式構建新的元素集合並返回(ht.List 陣列型別)
setInterval(function() {
datas.forEach(function(data) {
var info = infos[Math.floor(Math.random() * len)];
var shadowName = info.shadowColor;
var bgName = info.background;
if (data.a(shadowName) === 'rgba(255, 0, 0, 0.35)') { // 若節點業務屬性“陰影”顏色為紅色,則設定為綠色
data.a(shadowName, 'rgba(0, 255, 0, 0.35)');
}
else { // 若節點業務屬性“陰影”顏色為綠色,則設定為紅色
data.a(shadowName, 'rgba(255, 0, 0, 0.35)');
}
if (data.a(bgName) === 'rgb(255, 0, 0)') { // 若節點業務屬性背景顏色為紅色,則設定為綠色
data.a(bgName, 'rgb(0, 255, 0)');
}
else { // 若節點業務屬性背景顏色為綠色,則設定為紅色
data.a(bgName, 'rgb(255, 0, 0)');
}
});
}, 1000);
結束語
整體來說這個 Demo 還是比較有價值的,一是快速實現了 3D 機櫃模型,二是對模型上的元素進行了資料繫結。只是想讓你們知道,清晰的圖片繪製沒有那麼難~ 3D 的世界沒有那麼難~ 資料繫結也沒有那麼難!我希望也能讓您發現這並不是件難事。
相關文章
- WebGL 3D 電信機架實戰之資料繫結Web3D
- 基於HTML5的WebGL電信網管3D機房監控應用HTMLWeb3D
- 基於 HTML5 WebGL 的 3D 挖掘機HTMLWeb3D
- 基於 HTML5 WebGL 的 3D 機房HTMLWeb3D
- WebGL入門之基於WebGL的3D視覺化引擎介紹Web3D視覺化
- .NET基礎之資料繫結
- 基於 HTML5 WebGL 的 3D 科幻風機HTMLWeb3D
- 基於CarbonData的電信時空大資料探索大資料
- 基於 HTML5 + WebGL 的 3D 風力發電場HTMLWeb3D
- 基於 WebGL 的 3D Chart 圖表Web3D
- 基於 WebGl HTML5 的 3D 視覺化機房WebHTML3D視覺化
- 基於vue實現的雙向資料繫結Vue
- 基於HTML5 WebGL的工業化3D電子圍欄HTMLWeb3D
- 基於HTML5的電信網管3D機房監控應用HTML3D
- 資料繫結之謎
- 基於 WebGL 的 HTML5 網路拓撲結構 3D 圖WebHTML3D
- 基於 HTML5 WebGL 的 3D 網路拓撲結構圖HTMLWeb3D
- 基於 HTML5 的網路拓撲圖之 DataBinding 資料繫結HTML
- 基於 HTML5 WebGL 的 3D 風機視覺化系統HTMLWeb3D視覺化
- 基於 HTML5 WebGL 的挖掘機 3D 視覺化應用HTMLWeb3D視覺化
- 基於 HTML5 的 WebGL 3D 隧道監控HTMLWeb3D
- 基於 HTML5 WebGL 的發動機 3D 視覺化系統HTMLWeb3D視覺化
- WebGL之3D地球Web3D
- 基於 HTML5 + WebGL 的 3D 風力發電場視覺化系統HTMLWeb3D視覺化
- 基於HTML5 WebGL實現3D飛機葉輪旋轉HTMLWeb3D
- 基於 WebGL 的 HTML5 3D 工控裙房系統WebHTML3D
- 基於 HTML5 WebGL 的 3D 模型斜面生成HTMLWeb3D模型
- 基於 WebGL HTML5 的 3D 模型分離控制WebHTML3D模型
- 基於 HTML5 WebGL 的 3D 工控裙房系統HTMLWeb3D
- 基於Web的6個完美3D圖形WebGL庫Web3D
- 基於 HTML5 WebGL 的 3D “彈力”佈局HTMLWeb3D
- 基於 WebSocket 實現 WebGL 3D 拓撲圖實時資料通訊同步(一)Web3D
- 基於 WebSocket 實現 WebGL 3D 拓撲圖實時資料通訊同步(二)Web3D
- 如何編寫一個前端框架之五-基於 ES6 代理的資料繫結(譯)前端框架
- 【阿不】深入ASP.NET資料繫結(中)—資料雙向繫結機理ASP.NET
- 基於HTML5的WebGL經典3D虛擬機器房漫遊動畫HTMLWeb3D虛擬機動畫
- 基於 HTML5 WebGL 的 3D 網路拓撲圖HTMLWeb3D
- 基於 WebGL 的 HTML5 3D 網路拓撲圖WebHTML3D