基於 WebGL 的 HTML5 3D 智慧樓宇監控系統
前言
智慧監控已經涉及到了各大領域,工控、電信、電力、軌道交通、航天航空等等,為了減少人員的消耗,監控系統必不可少。之前我寫過一篇 2D 的智慧地鐵監控系統廣受好評,突然覺得,既然 2D 的這麼受歡迎,那麼 3D 的需求量肯定也是非常大的,3D 畢竟比 2D 來說還是更直觀一些,於是有了這個例子以及這篇文章。智慧監控系統在 3D 中應用比較廣泛的除了 3D 機房以外,我覺得就是樓宇的監控了,可是之前做了很多關於機房方面的 Demo,所以最終決定做 3D 樓宇監控系統。
程式碼生成
場景搭建
整個場景是由 HT for Web 的 3D 元件搭建而成,配合左側的 listView 列表元件,通過點選這個 listView 列表元件中的各個項可以自由切換各個監控樓層和樓宇的場景:
dm = new ht.DataModel();
g3d = new ht.graph3d.Graph3dView(dm);
relativeLayout = new ht.ui.RelativeLayout(); // 相對佈局器 可對介面進行佈局
var ht3dView = new ht.ui.HTView(g3d); // 放置 3d 元件
relativeLayout.addView(ht3dView, { // 給相對佈局器新增元件顯示,引數一為元件名稱,引數二可設定寬高、對齊方式等屬性
width: 'match_parent',
height: 'match_parent'
});
var listView = window.list = new ht.ui.ListView(); // 列表元件
for (var i = 1; i <= 15; i++) {
var data = new ht.Data(); // 建立節點
data.setName('樓層' + i); // 設定節點名稱
listView.dm().add(data); // 將節點新增進列表元件中
}
relativeLayout.addView(listView, { // 將 listView 元件新增進佈局器中
align: 'left', // 設定對齊方式為左對齊
vAlign: 'top', // 設定垂直對齊方式為頂部對齊
marginTop: 120, // 設定外邊距頂部為 120 畫素
marginLeft: 60, // 設定外邊距左側為 60 畫素
width: 80, // 設定寬度為 80
height: 480, // 設定高度為 480
index: 100 // 設定元素的堆疊順序
});
relativeLayout.addToDOM(); // 將元件新增進 body 中
載入模型
進入頁面顯示的就是整個城市的場景,通過 ht.Default.loadObj 方法載入 obj 模型:
var loadCity = function(){
ht.Default.loadObj('obj/city.obj', 'obj/city.mtl', { // 載入模型
center: true, // 模型是否居中,預設為 false,設定為 true 則會移動模型位置使其內容居中
cube: true, // 是否將模型縮放到單位1的尺寸範圍內,預設為 false
prefix: 'obj/', // 圖片路徑字首,即在 map_kd 值之前增加的字首,如果是相對路徑則以載入 obj 的 html 頁面的路徑為參考
shape3d: 'city', // 如果指定了 shape3d 名稱,則HT將自動將載入解析後的所有材質模型構建成陣列的方式,以該名稱進行註冊
finishFunc: function(modelMap, array, rawS3){ // 用於載入 obj 模型後的回撥處理
city.rawS3 = rawS3; // 設定變數 city 物件的 rawS3 屬性 此函式中的 rawS3 屬性為 obj 模型的原始大小
showCity(); // 建立一個節點 設定節點的 shape3d 為 city 顯示 city.obj 與 city.mtl 的內容
}
});
}
工控樓層模型的載入也是類似,這裡就不再贅述。
直接將元件新增進場景中是不會有相關的操作的, 必須要監聽事件的觸發才可進行後續的操作,這裡對資料選中容器中的選中變化事件進行監聽:
// 列表點選
listView.dm().sm().ms(function(e){ // 監聽選中變化事件
if (e.kind === 'set') { // 設定監聽事件
showFloor(); // 顯示樓層
}
});
呼叫模型
這裡為了簡單就只設定了一個工控樓層的 obj 模型,通過呼叫不同的 obj 模型可以顯示不同的工控樓層場景,也就是說我們可以自己通過 ht.Default.loadObj 方法載入模型,設定工控樓層模型的 shape3d 屬性,然後設定到節點的 shape3d 屬性上,即可修改;或者直接設定節點的 shape3d 屬性為 json 格式的 obj 檔案,這裡還是採取第一種方式:
var showFloor = function(){
g3d.setCenter([210, 0, 210]); // 設定 3d 元件的“中心”位置
dm.clear(); // 清除資料容器中的所有節點
var rawS3 = floor.rawS3, // 獲取 obj 模型的原始大小
node = new ht.Node(); // 建立一個新的節點
node.s({ // 設定節點的樣式屬性
'shape3d': 'floor', // 此項設定的值為 ht.Default.loadObj 中設定的 shape3d 屬性的值
'wf.visible': 'selected', // 設定選中節點時顯示節點外部的線框
'3d.selectable': false // 設定節點不可選中
});
node.s3(rawS3[0] / 10,rawS3[1]/ 10,rawS3[2] / 10); // 設定節點的大小為原始大小的十分之一
node.p3(140, 0, 230); // 設定節點的位置
dm.add(node); // 將節點新增進資料容器中
// 新增四個“相機”的節點
createNode([0, 20, 0]);
createNode([110, 20, 220]);
createNode([330, 20, 420]);
createNode([210, 20, 120]);
createNode([420, 20, 120]);
};
這裡順便說一下另一種簡便的呼叫 obj 模型的方式,直接設定節點的 shape3d 屬性為匯入的 json 格式的檔案:
var node = new ht.Node();
node.s("shape3d", "./symbols/city.json");
但是這個 json 的內容必須要有以下幾個元素:
{
"modelType": "obj", // 必須設定此屬性為 obj 格式
"obj": "./obj/city.obj", // 必須設定 obj 屬性
"mtl": "./obj/city.mtl" // 此項可寫可不寫,如果需要設定 obj 模型的樣式(如顏色等),則必須設定此項
}
但是這種模式不適用於這個場景,因為我的模型有些大,需要呼叫到 obj 模型的原始大小 rawS3 屬性除以一定比例後再顯示。
建立面片
上面提到了 createNode 方法,這個方法主要是用來建立顯示為“面片”型別的節點。所謂“面片”,即為只有一個面。通過這種在一個面上顯示一張向量圖的方式,結果會比在一個六面體上顯示一張圖的效能好, HT 3D 場景簡單的時候可能看不出來效果,如果場景卡頓,立馬就能看出“面片”的優勢了:
function createNode(p3, s3){
var node = new ht.Node(); // 建立一個新的節點
node.p3(p3); // 設定節點的位置
// node.s3(s3);
node.s({
'shape3d': 'billboard', // 設定節點的 shape3d 型別為 billboard 型別,顯示為“面片”
'shape3d.image': './symbols/智慧樓宇/camera.json', // 3d圖形整體貼圖
'shape3d.image.cache' : true, // 如果貼圖是向量,是否快取(快取後效能會得到提升)
'shape3d.autorotate': true, // 是否自動朝向相機
'shape3d.transparent': true, // 決定3d圖形是否透明
'shape3d.alwaysOnTop': true,// 是否總是在最前
'shape3d.fixSizeOnScreen': [ 38, 47 ] // 是否無論縮放遠近,在螢幕內呈現固定大小,值可為 true(使用圖片或向量自身大小)/false, 也可以是[100, 200](對應寬高)
});
dm.add(node); // 將節點新增進資料容器中
g3d.invalidateShape3dCachedImage(node); // cache 的代價是,這裡需要更新
return node;
}
事件互動
然後我就在想,既然到了樓層的 3D 模型顯示,那麼怎麼返回?以哪種方式返回最好?想來想去比較沒有違和感的還是點選列表元件比較好,就選中了列表元件的頂部:
listView.getView().addEventListener('click', function(e){ // 監聽點選事件
e.preventDefault(); // 阻止預設操作
if (e.clientY - 120 < 50) {
showCity(); // 顯示初始 3D 樓宇場景
listView.dm().sm().cs(); // 列表設定清除所有選中元素
}
});
所有程式碼結束!
總結
這個 3D 智慧樓宇監控系統非常的簡單,對於技術人員來說是完全沒有挑戰性的,主要工作內容在美工上,這麼一來,如果要新增比較複雜的需求,技術人員就可以全身心地投入到產品上,而不是一些繁瑣的 3D 模型的搭建了。總而言之,我覺得這個 Demo 非常具有代表性,所以想拿出來跟大家分享一下,一起討論一下前端的趨勢所在。
相關文章
- 基於 HTML5 的 WebGL 3D 智慧樓宇監控系統HTMLWeb3D
- 基於 HTML5 WebGL 的 智慧樓宇能源監控系統HTMLWeb
- 基於 WebGL 的 HTML5 樓宇自控 3D 視覺化監控WebHTML3D視覺化
- 基於 HTML5 的 WebGL 樓宇自控 3D 視覺化監控HTMLWeb3D視覺化
- 基於 WebGL 的 HTML5 3D 棉花加工監控系統WebHTML3D
- 基於 HTML5 WebGL 的 3D 棉花加工監控系統HTMLWeb3D
- 基於 HTML5 的 WebGL 3D 隧道監控HTMLWeb3D
- 基於 HTML5 Canvas 的樓宇自控系統HTMLCanvas
- 基於 HTML5 WebGL 的故宮人流量動態監控系統HTMLWeb
- 基於 WebGL 的 HTML5 低碳工業園區監控系統WebHTML
- 基於 HTML5 WebGL 的低碳工業園區監控系統HTMLWeb
- 智慧樓宇管控系統整合智慧安防系統開發
- 基於 WebGL 的 HTML5 3D 工控裙房系統WebHTML3D
- 基於 HTML5 WebGL 的 3D 工控裙房系統HTMLWeb3D
- 基於 HTML5 WebGL 的加油站 3D 視覺化監控HTMLWeb3D視覺化
- 基於 HTML5 的 WebGL 自定義 3D 攝像頭監控模型HTMLWeb3D模型
- 於 HTML5 WebGL 的民航客機飛行監控系統HTMLWeb
- 基於 HTML5 + WebGL 的太陽系 3D 展示系統HTMLWeb3D
- 基於 HTML5 WebGL 的 3D 倉儲管理系統HTMLWeb3D
- 基於HTML5的WebGL電信網管3D機房監控應用HTMLWeb3D
- 基於 HTML5 + WebGL 的無人機 3D 視覺化系統HTMLWeb無人機3D視覺化
- 基於 WebGL 的 HTML5 3D SCADA 主站系統WebHTML3D
- 基於 HTML5 WebGL 的 3D SCADA 主站系統HTMLWeb3D
- 樓宇控制系統解決方案,樓宇自控系統
- 基於 HTML5 + WebGL 的太陽系 3D 視覺化系統HTMLWeb3D視覺化
- 基於 HTML5 WebGL 的 3D 風機視覺化系統HTMLWeb3D視覺化
- 基於 WebGL 的 HTML5 3D 工控隧道視覺化系統WebHTML3D視覺化
- 智慧樓宇節能監控物聯網解決方案
- 基於 HTML5 WebGL 的發動機 3D 視覺化系統HTMLWeb3D視覺化
- 基於 HTML5 的 WebGL 3D 地鐵站視覺化系統HTMLWeb3D視覺化
- 基於 HTML5 WebGL 的地鐵站 3D 視覺化系統HTMLWeb3D視覺化
- 基於 HTML5 WebGL 的 3D 挖掘機HTMLWeb3D
- 基於 HTML5 WebGL 的 3D 機房HTMLWeb3D
- 基於 HTML5 WebGL 構建智慧城市 3D 場景HTMLWeb3D
- 基於 HTML5 WebGL 的垃圾分類系統HTMLWeb
- 基於 WebGL 3D 的 HTML5檔案館視覺化管理系統Web3DHTML視覺化
- 基於 HTML5 WebGL 的 3D 渲染引擎構建工廠運作系統HTMLWeb3D
- 基於 HTML5 的 WebGL 3D 檔案館視覺化管理系統HTMLWeb3D視覺化