基於 HTML5 WebGL 的 水泥工廠可視化系統

前言

    現在的製造行業,基於數據進行生產策略制定與管理已經成爲一種趨勢,特別是 工業4.0 的浪潮下,數據戰略已經成爲不少製造企業的優先戰略,而數據可視化以更直觀的方式,幫助指導決策,成爲數據分析傳遞信息的重要工具。經過數據可視化系統助力實現數據驅動的工業世界,爲 工業4.0 提供更加靈活、敏捷、高效、個性化的數據支撐。今天就給你們帶來一個採用 Hightopo 的 HT for Web 產品實現了一個水泥工廠可視化系統。html

系統預覽

 

 

本案例共有七個子系統:node

  • 數據概況 -- 展現全廠年月時間單位的各項數據概況
  • 窯系統運行 -- 用窯工藝流程動畫展現窯系統實時運行狀態
  • 系統運行狀況 -- 用動畫流程圖展現整個系統運行狀況
  • 生料質量控制 -- 用圖表和流程圖展現各類生料的配比狀況
  • 熟料質量控制 -- 用動畫流程圖展現各類熟料的配比狀況
  • 煤粉質量控制 -- 用圖表和流程圖對煤粉質量進行監控
  • 智能物流 -- 經過 3D 場景實時監控進出廠車輛,和各項原料運輸情

子系統頁面切換

      切換不一樣子系統時,左側菜單和頂部標題是不須要切換的,因此咱們把須要切換的內容部分別放在不一樣的 Block 中,Block 類型,自己不繪製任何內容,用於做爲其它節點的父節點,能夠與子節點同步大小,當它隱藏或顯示時,全部子節點都會跟着隱藏或顯示。因此當咱們切換子系統時只須要控制對應的 Block 顯示隱藏,而不須要去加載切換多張圖紙。json

流向地圖

 

    在數據概況頁面中,流向地圖展現年度水泥向各地區的銷售狀況,這裏咱們用 Shape 類型繪製線段來鏈接源地和匯地,用流動效果表示銷售關係。流動效果只需引入 HT 的 ht-flow.js 插件,便可經過簡單的屬性設置實現,代碼以下:ide

// 獲取線段的父節點 this.flowParent = dm.getDataByTag('saleFlowParent'); // 遍歷獲得全部線段 this.flowParent.eachChild(child => { // 開啓流動,設置流動樣式  child.s({ // 開啓流動 'flow': true, // 設置流動組中最大元素的尺寸 'flow.element.max': 4, // 設置流動組中的元素的漸變陰影中心顏色 'flow.element.shadow.begincolor': '#49e5fe', // 設置流動組中的最大元素的漸變陰影尺寸 'flow.element.shadow.max': 16, // 設置流動組中的元素的漸變陰影邊緣顏色 'flow.element.shadow.endcolor': 'rgba(73, 229, 254, 0)', }); });

 窯系統動畫

    在窯系統運行頁面中,窯工藝流程動畫很直觀的展現了窯系統實時運行狀態。畫面中火焰、水和熟料在傳送帶上運輸的動畫效果,爲了在性能較差的設備上也能流暢運行,我經過切換不一樣矢量圖形的方式實現。這裏用到了 HT 矢量中狀態機制,先繪製多個不一樣的矢量組件,每一個組件均可以定義狀態來決定本身在哪一個狀態下顯示,只要經過 data.s('state') 修改節點狀態就能夠實現以下效果:函數

    使用一個定時器,不斷地改變節點的狀態值,相關代碼以下:工具

this._stateTimer = setInterval(() => { stateNodes.forEach(node => { this.stateAnimation(node); }); }, 180); //切換狀態 stateAnimation(node) { let stateIndex = (node.a('stateIndex') || 0) % stateEnum.length, state = stateEnum[stateIndex].value; node.s('state', state); node.a('stateIndex', ++stateIndex); }

 

流程圖動畫

    流程圖中流動線一樣是使用 ht-flow.js 插件實現。因爲圖紙上的線段比較多,我把不一樣的線段分組放在不一樣的 Block 下,遍歷其子節點設置樣式,代碼以下:佈局

  //設置流動屬性  setNodeFlow (data, value) { if (data instanceof ht.Block) { data.eachChild(child => { this.setNodeFlow(child, value); }); } else if (data.getDisplayName() === 'line'){ data.s({ 'flow': value, 'flow.element.max': 4, 'flow.element.count': 1, 'flow.count': 5, 'flow.step': 10 }); } } //設置虛線流動屬性 setNodeDashFlow(data, value) { if (data instanceof ht.Block) { data.eachChild(child => { this.setNodeDashFlow(child, value); }); } else if (data.getDisplayName() === 'border'){ if (value) { data.s({ 'shape.dash.flow': true, 'shape.dash': true }); } else { data.s({ 'shape.dash.flow': false, 'shape.dash': false }); } } }

    爲了使動畫看起來更順暢,我給一些節點加上透明度動畫,設置節點透明度的代碼以下:性能

//設置節點透明度 setNodeOpacity (data, value = 0.5) { if (data instanceof ht.Block) { data.eachChild(child => { this.setNodeOpacity(child, value); }); } else { data.s('opacity', value); } }

    接下來只須要依次執行動畫:動畫

//開始流程圖動畫 start() { let {eo, eoInput, eoLine1, eoKind, eoCalu} = this; //工況輸入透明度動畫 this.gv.enableFlow(30); this.setNodeOpacity(eo); this.setNodeFlow(eo, false); (new Promise((resolve, reject) => { this.animtion = startAnim({ frames: 16, interval: 5, finishFunc: () => {resolve()}, action: (v, t) => { this.setNodeOpacity(eoInput, 0.5 + 0.5 * v); } }); })).then(() => { //連線連線透明動畫,流動 return new Promise((resolve, reject) => { this.animtion = startAnim({ frames: 12, interval: 10, finishFunc: () => { this.setNodeFlow(eoLine1, true); this.timer = setTimeout(() => {resolve()}, 1500); }, action: (v, t) => { this.setNodeOpacity(eoLine1, 0.5 + 0.5 * v); } }); }) }).then(() => { //軟計算透明動畫 return new Promise(resolve => { this.animtion = startAnim({ frames: 16, interval: 5, finishFunc: () => {resolve()}, action: (v, t) => { this.setNodeOpacity(eoKind, 0.5 + 0.5 * v); this.setNodeOpacity(eoCalu, 0.5 + 0.5 * v); } }); }); }).then(() => { //軟計算透明虛線流動 return new Promise(resolve => { this.setNodeDashFlow(eoKind, true); this.setNodeDashFlow(eoCalu, true); this.timer = setTimeout(() => { this.setNodeDashFlow(eoKind, false); this.setNodeDashFlow(eoCalu, false); resolve(); }, 3000); }); }).then(() => { ...... }) }

 

智能物流

    前面六個子系統均爲 2D 界面,而智能物流頁面則是嵌入了一個 3D 場景。實現方式是經過定義 HT 矢量 JSON 的 renderHTML 函數屬性,可實如今 GraphView 拓撲圖上,嵌入任意第三方 HTML DOM 元素。不過這裏也要注意一點,HT 的圖紙是 Canvas 實現的,renderHTML 的 DOM 元素必定在 Canvas 之上,使用 renderHTML 的 DOM 與常規 Canvas 上繪製的圖元不可能有層級控制可能性。下面展現一下 renderHTML 函數屬性裏的代碼:ui

renderHTML : function (data, gv, cache) { // 避免重複建立g3d if (!cache.g3d) { // 建立 3D 視圖組件 var g3d = cache.g3d = new ht.graph3d.Graph3dView(); // 佈局函數,根據圖元的位置信息擺放HTML元素 g3d.layoutHTML = function () { gv.layoutHTML(data, g3d, true); }; // 阻止事件冒泡 g3d.getView().addEventListener('mousedown', function (event) { event.stopPropagation(); }); g3d.getView().addEventListener('touchstart', function (event) { event.stopPropagation(); }); } // 獲取圖元自定義屬性sceneURL的值 var sceneURL = data.a('sceneURL'); // 獲取圖元自定義屬性onPostDeserialize的值 var onPostDeserialize = data.a('onPostDeserialize'); // 當圖元自定義屬性sceneURL改變時,清除舊dataModel,反序列化新的sceneURL if (cache.g3d.sceneURL !== sceneURL) { cache.g3d.dm().clear(); cache.g3d.sceneURL = sceneURL; if (sceneURL) { cache.g3d.deserialize(sceneURL, function (json, dm, g3d, datas) { // 在反序列化後的回調函數中,執行onPostDeserialize函數 onPostDeserialize && onPostDeserialize(json, dm, g3d, datas); }); } } return cache.g3d; }

     3D場景嵌入後,接下來實現水泥廠內的車輛動畫。根據後臺傳來車輛進入工廠的數據,咱們建立運載不一樣原料的車輛模型,讓它們沿着不一樣的路徑抵達對應的廠房。一樣是用 Shape 類型事先繪製好路徑,根據 Shape 的 Points 和 Segments 信息,實現車輛沿着路徑行駛動畫。相關代碼以下:

 carAnimation(car, path, duration) {
        // 車輛行駛動畫  ht.Default.startAnim({ duration: duration, easing: Easing.easeNone, action: function (v, t) { // 設置偏移量 let offset = Math.floor(v * 100); // 根據偏移量獲得在路徑上的點座標 let position = ht.Default.getPercentPositionOnPoints(path.getPoints(), path.getSegments(), offset); // 根據偏移量獲得在路徑上的點於路徑切線角度 let angle = ht.Default.getPercentAngle(path.getPoints(), path.getSegments(), offset); // 設置車輛位置座標及旋轉角度  car.setX(position.x); car.setY(position.y); car.setRotationY(Math.PI / 2 - angle); }, }); }

總結

    工業互聯網是工業發展的必經之路,咱們國家是一個工業大國,正處在工業轉型升級的關鍵時刻,面臨着人工成本上升、原材料價格波動、貿易競爭日益加重等問題,迫切須要提升效率、下降生產成本。只有堅決不移地推進工業互聯網落地,加快更多企業的數字化轉型和智能化改造,纔有能讓在全球化競爭中立於不敗之地。可視化做爲智能化數字化的最後一環,讓複雜抽象的數據變得真正可知可感,幫助決策者發現規律,洞悉將來,爲企業提速增效。

    還有更多的可視化案例能夠參考:https://www.hightopo.com/demos/index.html

相關文章
相關標籤/搜索