得益於 HTML5 WebGL 技術的成熟,從技術上對工控管理的可視化,數據可視化變得簡單易行!完成對工控設備的管理效率,資源管理,風險管理等的大幅度提升,同時也對國家工業4.0計劃做出有力響應!javascript
如本案例所示,是一個基於 HTML5 WebGL 技術實現的計量站三維可視化監控系統,在本案例中,具體宏觀的展現一個油田站點的總體場景,而後點擊能夠進入內景看到油田計量站內景的具體狀況,同時能夠看到各個設備的參數的當前狀態。java
一樣的其中功能組件具備很高的複用性,因此也會很是方便的應用到其餘場景中!json
以下所示,即是本案例運行動態圖:dom
此項目連接:基於 HTML5 WebGL 的計量站三維可視化監控系統 Web 組態工控應用函數
(www.hightopo.com/demo/meteri… ) 動畫
在這個場景中主要有以下幾個功能:一、點擊來回切換場景;ui
二、管線流動效果;spa
三、數據面板動態顯示;3d
確認功能需求後就能夠開始實施實現,動手實現以前要先確認場景有哪些,以下所示主要有油田外景和內景。code
外景:
內景:本 demo 須要掌握 HT for Web 的 2d 和 3d 相關 技術,具體技術參考資料能夠去 HT for Web 官網圖撲軟件瞭解。
一、 默認視角 在三維場景中,須要先設置一個默認視角,當從新打開頁面時候直接回到默認視角,經過 setFar, setEye 和 setCenter 方法實現。
gv.setFar(100000);
gv.setEye([1247, 600, 1972]);
gv.setCenter([0, 0, 0]);
複製代碼
二、 視角限制 因爲三維場景的特性,若是不做出視角限制,就會出現穿模,翻底等現象,尤爲本案例有天空球效果,若是不做出視角限制當用戶無限拉遠後會出現視角跑到天空球外,場景消失問題,這將會很是尷尬!
具體實現是經過 setEye 方法和 setCenter 方法控制場景的 eye 和 center 變量實現,放置到 mp 函數內。
mp(listener, scope, ahead); // 增長自身屬性變化事件監聽器
複製代碼
// 限制 eye
gv.mp(function (e) {
if (e.property === 'eye') {
if (gv.getEye()[1] < 90) {
gv.getEye()[1] = 90;
}
if (gv.getEye()[1] > 1500) {
gv.getEye()[1] = 1500;
}
if (gv.getEye()[0] > 2400) {
gv.getEye()[0] = 2400;
}
if (gv.getEye()[0] < -2400) {
gv.getEye()[0] = -2400;
}
if (gv.getEye()[2] > 2500) {
gv.getEye()[2] = 2500;
}if (gv.getEye()[2] < -2400) {
gv.getEye()[2] = -2400;
}
}
})
複製代碼
三、 點擊切換場景 經過 mi 添加交互事件監聽器爲要點機交互模型綁定事件,經過 e.kind 判斷點擊事件,而後經過 tag 標籤名獲取要點擊交互的模型對象。
首先在點擊時候有個拉近效果和周圍模型透明化效果,則是經過 flyTo 實現拉近效果和 setStyle 方法實現拉近後其餘模型透明化。
具體代碼以下:
gv.mi(function (e) {
if (e.kind === 'clickData') {
for (var i = 1; i <= 2; i++) {
if (e.data.getTag() === 'engineRoom' + i) {
// 點擊拉近場景
gv.flyTo(e.data, {
animation: true,
distance: 500
});
// 選中模型實化
e.data.setStyle('shape3d.transparent', false);
e.data.setStyle('shape3d.opacity', 1);
// 其餘模型透明化
dm.each(data => {
if (data.getTag() != 'engineRoom' + i) {
data.setStyle('shape3d.transparent', true);
data.setStyle('shape3d.opacity', 0.3);
data.setStyle('all.transparent', true);
data.setStyle('all.opacity', 0.5);
}
})
}
}
}
})
複製代碼
實現效果以下:
而後在完成拉近場景和透明化其餘模型後,開始實現場景切換效果。場景切換的核心是經過 gv.deserialize() 反序列化顯示路徑對應場景,經過輸入場景路徑參數,在回調函數內完成場景渲染顯示,代碼以下:
gv.deserialize('scenes/油田.json', function (json, dm, gv, datas) {
if (json.title) document.title = json.title;
if (json.a['json.background']) {
var bgJSON = json.a['json.background'];
if (bgJSON.indexOf('displays') === 0) {
var bgGv = new ht.graph.GraphView();
bgGv.deserialize(bgJSON);
bgGv.addToDOM();
graphView.addToDOM(bgGv.getView());
}
else if (bgJSON.indexOf('scenes') === 0) {
var bgG3d = new ht.graph3d.Graph3dView();
bgG3d.deserialize(bgJSON);
bgG3d.addToDOM();
graphView.addToDOM(bgG3d.getView());
}
graphView.handleScroll = function () { };
}
})
複製代碼
但在這以前有一個問題,就是如何處理當前場景和經過反序列化渲染顯示場景的關係,若是不做處理,就會出現當前場景和要切換顯示的場景重合問題,因此在點擊切換場景過程當中,要先清空當前場景,爲後來要切換的場景騰出地方。
因此在前面要先加一行代碼:
dm.clear();
複製代碼
作完處理後,如今是完成了切換過去效果,但還有要切換回來的功能,這個實現很是簡單,取了個巧,直接 window.location.reload(); 刷新頁面就好。
最終這部分完整代碼以下:
function jump(position3d) {
var timer = setInterval(function () {
clearInterval(timer)
var distance = ht.Default.getDistance(gv.getEye(), position3d);
if (distance <= 501) {
var home = g2d.dm().getDataByTag('home');
home.s('2d.visible', true);
var line = g2d.dm().getDataByTag('line');
line.s('2d.visible', true);
dm.clear();
gv.deserialize('scenes/油田.json', function (json, dm, gv, datas) {
if (json.title) document.title = json.title;
if (json.a['json.background']) {
var bgJSON = json.a['json.background'];
if (bgJSON.indexOf('displays') === 0) {
var bgGv = new ht.graph.GraphView();
bgGv.deserialize(bgJSON);
bgGv.addToDOM();
graphView.addToDOM(bgGv.getView());
}
else if (bgJSON.indexOf('scenes') === 0) {
var bgG3d = new ht.graph3d.Graph3dView();
bgG3d.deserialize(bgJSON);
bgG3d.addToDOM();
graphView.addToDOM(bgG3d.getView());
}
graphView.handleScroll = function () { };
}
})
}
}, 500)
}
複製代碼
我將它放置到 jump 函數內,而後將 jump 函數放到前面點擊事件中調用,讓代碼總體簡潔一些。
實現效果以下圖:
四、 管線流動效果和動態數據面板 最後兩個功能實現很是簡單,我就放到一塊來講。首先效果以下圖所示:
管線流動效果的實現核心就是控制 UV 貼圖偏移,因此經過動畫控制器 startAnim 控制 UV 貼圖偏移量就能夠實現,在動畫結束時,在 finishFunc 內回調函數便可實現動畫循環。pipelineAnim(0.1)
function pipelineAnim(offset1) {
var anim1 = ht.Default.startAnim({
duration: 2000,
action: function () {
offset1 += 0.015;
var pipelines = gv.dm().getDataByTag('pipeline');
pipelines.setStyle('shape3d.uv.offset', [-offset1, 0]);
},
finishFunc: function () {
pipelineAnim(offset1);
}
})
}
複製代碼
數據面板則是經過定時器在固定間隔時間循環執行賦予隨機數便可,在這裏經過隨機數模擬真實數據,在實際當中是經過和後臺對接實現真實數據動態變化,代碼以下:
setInterval(function () {
for (var i = 1; i <= 4; i++) {
var panels = gv.dm().getDataByTag('panel' + i);
for (var j = 1; j <= 3; j++) {
if (panels.a('text' + j) != undefined) {
var num = parseFloat(Math.random() * (100 - 10 + 1) + 10, 10).toFixed(2);
var textJson = { "參數名": "出口溫度", "參數值": num, "參數單位": panels.a('text' + j)['參數單位'] };
panels.a('text' + j, textJson);
}
}
}
}, 1000)
複製代碼
以上即是我今天給你們帶來的工控案例,但願各位看官可以喜歡本 demo,在本案例中可以獲得一些啓發。