// 控制是否載入 obj 的四邊面,否的話經過算法合併三角面 ht.Style['wf.loadQuadWireframe'] = false; // 控制是否顯示四邊面 ht.Style['wf.combineTriangle'] = true;
在風格基調肯定後,在主體大樓場景作還須要作一些簡單的事件機制處理,例如模型選中狀態的表現和設備預警信息彈窗的顯示。html
模型狀態的體現是開啓了模型選中的外框高亮顯示:node
// 開啓模型選中高亮線框寬度爲1 g3d.getHighlightHelper().mode = 1;
開啓了模型選中高亮後,咱們能夠很清晰地體現出所點擊的模型,搭配上點擊事件的處理,設備信息彈窗的展現,在交互體驗上就會有一種很友好的效果展現。對於設備信息的彈窗展現,是先經過對設備進行綁定標籤,而後經過這個惟一的標籤在數據模型 dataModel 去找到這個設備,而後彈出相對應的彈窗信息或者預警事件。算法
// 根據惟一標識標籤從數據模型中獲取節點信息 this.equipmentPanel = g3dDm.getDataByTag('equipmentPanel'); this.alarmEquipmentPanel = g3dDm.getDataByTag('alarmEquipmentPanel'); this.buildingPanel = g3dDm.getDataByTag('buildingPanel'); handleInteractive(e) { // 獲取事件類型 kind 和事件處理節點 data const {kind, data} = e; if (kind === 'clickData') { let tag = data.getTag(); if (!tag) return; if (tag === 'equipment') { // 獲取所點擊設備的位置信息 var p3d = data.getPosition3d(); // 設備位置信息上對應空間座標 Y 軸上設定增長20的高度 p3d[1] = p3d[1] + 20; // 獲取設備面板 var panel = this.equipmentPanel; // 設備面板顯示展現 panel.s('3d.visible',true); // 設置設備面板座標 panel.setPosition3d(p3d); // 隱藏大樓面板和預警面板 this.buildingPanel.s('3d.visible',false); this.alarmPlane.s('3d.visible',false); } if (tag === 'alarmEquipment') { // 獲取所點擊設備的位置信息 var p3d = data.getPosition3d(); // 設備位置信息上對應空間座標 Y 軸上設定增長20的高度 p3d[1] = p3d[1] + 20; // 獲取預警面板 var panel = this.alarmEquipmentPanel; // 預警面板顯示展現 panel.s('3d.visible',true); // 設置預警面板座標 panel.setPosition3d(p3d); // 隱藏大樓面板和設備面板 this.buildingPanel.s('3d.visible',false); this.equipmentPanel.s('3d.visible',false); } if(tag === 'building'){ // 顯示大樓面板 this.equipmentPanel.s('3d.visible',true); // 隱藏設備面板 this.alarmEquipmentPanel.s('3d.visible',false); // 隱藏預警面板 this.buildingPanel.s('3d.visible',false); } } // 點擊背景則隱藏全部面板信息 if(kind === 'clickBackground'){ this.equipmentPanel.s('3d.visible',false); this.alarmEquipmentPanel.s('3d.visible',false); this.buildingPanel.s('3d.visible',false); } }
// 遍歷數據模型獲取所要尋找的標識節點作相應的動畫 g3dDm.each((data) => { // 獲取節點標識 let tag = data.getTag(); if (tag === 'num') { // 數字飛昇動畫 animNum(data); } else if (tag === 'car') { // 設置車輛節點的初始 uv 偏移 data.s('top.uv.offset', [1, 0]); // 車輛穿梭動畫 animCar(data); } else if (tag === 'light') { //光柱飛昇動畫 animLight(data); } });
而全部動畫效果的實現,都是基於 HT 封裝的 ht.Default.startAnim() 動畫函數,支持 Frame-Based 和 Time-Based 兩種方式的動畫,本可視化系統中採起的是後面一種實現方式,經過 duration 對於動畫時間的控制和 easing 讓用戶自定義,經過數學公式控制動畫,如勻速變化,先慢後快等效果。基於動畫函數的實現上,對各自展現節點的效果表現上,又封裝了三個函數作對應的處理。dom
數字飛昇動畫效果實現的封裝函數爲:函數
function animNum(data) { // 設置節點大小的範圍隨機數處理 var temp3 = 16 - 8 * (Math.random()); // 設置動畫運行時間的範圍隨機數處理 var temp4 = 1200 + Math.random() * 2000; // 設置節點在空間座標 Y 軸上的範圍隨機高度 var temp5 = 400 + Math.random() * 200; // 開啓動畫函數 ht.Default.startAnim({ duration: temp4, easing: function (t) { return t * t }, action: function (v, t) { // 獲取節點的位置座標信息 var p3d = data.getPosition3d(); // 設置節點的新位置座標信息 data.setPosition3d(p3d[0], temp5 - temp5 * v, p3d[2]); // 設置節點的大小信息 data.setSize3d(temp3, temp3, temp3); }, // 動畫函數結束後繼續回調此動畫函數 finishFunc: function () { animNum(data); } }); }
車輛穿梭動畫效果實現的封裝函數爲:動畫
function animCar(data) { // 開啓動畫函數 ht.Default.startAnim({ duration: 5000, easing: function (t) { return t }, action: function (v, t) { // 判斷節點的頂面貼圖是否爲所需的對應信息貼圖 if (data.s('top.image') === 'symbols/htdesign/填充/飛光漸變 2.png') { // 獲取節點的 uv 偏移信息 var offsetX = data.s('top.uv.offset')[0]; // 設置偏移新值到節點上 offsetX = (offsetX - 0.01) % 1; data.s('top.uv.offset', [offsetX, 0]); } }, // 動畫函數結束後繼續回調此動畫函數 finishFunc: function () { animCar(data); } }); }
而光柱的實現方式上也是與數字飛昇的效果同樣,經過在隨機的範圍位置座標內經過設定不一樣的時間差隨機生成,來造成與數字飛昇爲對立面的光柱降低效果,與線框建築的科技風格融爲一體,很好地詮釋了總體風格的展現,這裏對於光柱的動畫就再也不多加贅述了。ui
相對應的是,停車場隨機停放的效果展現,不一樣於以上的動畫視覺展現,自己仍是具備其效果意義的,能夠對接真實的數據進行對整個停車場的車輛安放作可視化的數據維護和管理,而咱們這裏的實現上,則很好地模擬了這一事件的處理方式,也是經過一個簡單的封裝函數來體現停車場的動畫效果:this
function animPark(data) { // 設置隨機值來體現車輛隨機停放的信息 var temp = Math.random(); // 根據隨機值判斷車輛安放的狀態 if (temp<0.15) { data.s('all.color','rgb(255,184,77)'); } else if (temp>0.6) { data.s('all.color','rgba(0,153,255,0.10)'); } ht.Default.startAnim({ duration: 2000, easing: function (t) { return t }, action: function (v, t) { }, // 動畫函數結束後繼續回調此動畫函數 finishFunc: function () { animPark(data); } }); }
g3d.flyTo(data, { direction: [0, 10, 10], animation: true, ratio: 0.9, });
對於門的開啓動畫,首先是將門設置對應的機櫃爲父節點,經過點擊事件的監聽處理後,根據多點擊的節點,將對應的門節點和旋轉角度信息,去調用門的封裝動畫函數:spa
// 傳入節點和旋轉角度信息 export function animDoor(data, x) { // 開啓動畫函數 ht.Default.startAnim({ duration: 1200, easing: function (t) { return t }, // 動畫執行函數,根據傳入的角度信息作旋轉角度的動畫 action: function (v, t) { data.setRotation3d(0,-v * x,0); }, finishFunc: function () { // 設置門的父節點機櫃透明度爲0.1 data.getParent().s('shape3d.opacity', 0.1); // 遍歷門的父節點機櫃並設置透明度爲0.1 data.getParent().eachChild(function (data) { data.s('shape3d.opacity', 0.1); }) } }); }
對於雙擊背景的視角返回處理,是經過 HT 封裝的相機移動函數 moveCamera(),能夠根據所要到達的視角中心(center)和眼睛(eye),經過開啓動畫函數達到一種視角切換的過渡效果:設計
g3d.moveCamera([1294, 898, 1671], [0, 0, 0], true);
對於機櫃所佔用的能耗和處理能力,能夠經過機櫃利用率來體現,這樣不只能直觀地體現每個機櫃的使用狀況,還能經過反饋的使用狀況,即時對一些負載的機櫃或者是低使用率的機櫃,作出智能調整,使其機櫃羣達到最大效率化的工做狀態。而具體的實現方法是經過在機櫃羣上動態生成,佔用機櫃高度比例大小的節點,經過隨機取值的方式,而且約定能耗顏色的顯示,來體現出機櫃當前的利用率信息。
loadCapacityNode(g3dDm, cabinetList) { cabinetList.forEach((data) => { // 建立新的利用率容量節點 var node = new ht.Node(); // 生成隨機數 var randomNumber = Math.random() * 100; // 經過隨機數值來體現對應的機櫃利用率顏色的變化 var color; if (randomNumber <= 30) { color = 'rgb(51,153,255)'; } else if (randomNumber > 30 && randomNumber < 60) { color = 'rgb(240,225,19)'; } else { color = 'rgb(242,83,75)'; } // 設置利用率容量節點的位置信息 node.p3(data.p3()); // 設置利用率容量節點的錨點信息 node.setAnchor3d(data.getAnchor3d()); // 設置利用率容量節點的高度信息 node.s3(data.getWidth(), data.getTall() * (randomNumber/100), data.getHeight()); // 設置利用率容量節點的一些基本屬性 node.s({ '3d.visible': false, '3d.movable': false, 'all.color': color, 'wf.visible': true, 'wf.color': 'rgb(247,247,247)' }); // 設置容量節點爲機櫃,方便返回房間視角的時候遍歷機櫃節點一併隱藏 g3dDm.add(node); this.capacityList.push(node); }) }