工業互聯網可視化系統風格的抉擇:線框模式之 3D 數據中心機房的實現


前言
3D 可視化,就是把復雜抽象的數據信息,以合適的視覺元素及視角去呈現,方便系統的展示、維護和管理。而在可視化系統的搭建選擇上,所呈現的風格樣式效果多種多樣,各自所突出的適用場合也不盡相同。對於科技風格上的體現, 線框模式可能是最具有代表性意義的實現方式之一。 機房數據可視化的管控維護的實現上,在 工業互聯網的推動下,體現的維護數據和系統搭建也越來越多樣化,而  Hightopo(以下簡稱 HT )的  HT for Web 產品上的有着豐富的組態化可供選擇,本文將介紹如何運用 HT 豐富的  2/3D 組態搭建出一個線框樓宇可視化機房的解決方案。
 
界面簡介及效果預覽
主頁面的呈現上以線框的科技風格為主的大樓設計,大樓環繞着數字飛升的光柱,場外分布着車流穿梭效果和停車場的模擬實現,其中數據中心上有着許多個設備的展示處理以及設備的預警處理,主體辦公大樓側邊並列呈現着樓層的分布——辦公樓層場景以及機房樓層場景;切換到內場景中的機房場景,展示了機房設備群的排列,單擊選中機櫃會視角轉化到此設備上,並且虛化周圍設備,展示出所點擊的機櫃信息,同時還具備一鍵切換查看機櫃的利用率信息;另外一個內場景辦公室,則起到了展示日常辦公的應用場景,可以添加維護的信息數據來管理。
 
 
系統分析
縱觀在工業互聯網的推動下,機房可視化系統的發展是極為重要的一環。而3D可視化作為一個可進行交互式、帶有多種視覺模擬體驗的機房管理平台,其具有機房資產、能源、環境等管理功能,對機房全方面集中監控、統一管理。這是作為機房內部數據監控的重要一環,而整體的風格搭建上,外部建築和設備采用的是科技風格的線框模式,在效果展示上可以更為的酷炫,交互體驗上也可以增值加分。
1、線框模式的科技風格搭建
在千篇一律的場景建築建模中,大部分都是實景上的搭建,感官上不同於科技風格的數字化展示來的震撼和酷炫,線框模式就很好地詮釋了這一風格。
 
2、3D 可視化數據中心機房監控管理系統的搭建與應用
3D 可視化數據中心機房集中監控管理系統對機房實現遠程集中監控管理,實時動態呈現設備告警信息及設備參數,快速定位出故障設備,使維護和管理從人工被動看守的方式向計算機集中控制和管理的模式轉變。
 
代碼實現
一、線框風格科技場景
在 3D 場景風格中,有着很多實現的方式選擇,而線框風格是最為體現科技感的一種實現方式。場景建築以及設備主體以線框風格展示,其中數據中心上的設備也會對應處理預警事件的展示。
線框模式是對於模型建模 obj 的一種特殊處理,機制封裝在 HT 本身里面,而我們在開啟線框模式的同時,可以選定一些建模風格上的限制,例如模型 obj 的四邊面或者三邊面就會影響到線框里線的繪制方式,這里通過合並三邊面,並且開啟顯示四邊面來起到線框風格上的簡潔體現:
// 控制是否載入 obj 的四邊面,否的話通過算法合並三角面
ht.Style['wf.loadQuadWireframe'] = false; 
// 控制是否顯示四邊面
ht.Style['wf.combineTriangle'] = true; 

在風格基調確定后,在主體大樓場景做還需要做一些簡單的事件機制處理,例如模型選中狀態的表現和設備預警信息彈窗的顯示。

模型狀態的體現是開啟了模型選中的外框高亮顯示:

// 開啟模型選中高亮線框寬度為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);
    }
}

 

二、3D 動畫效果的實現
在 3D 場景中有着許多動畫的集合,可以通過簡單清晰地體現出場景中一些所需的元素,例如車流穿梭、數字飛升以及停車場停放的效果,可以給靜態的場景添加活力。
通過標識獲取到對應的數字、車流和光柱節點,然后通過簡單封裝的動畫函數驅動實現出以上的效果狀態:
// 遍歷數據模型獲取所要尋找的標識節點做相應的動畫
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 讓用戶自定義,通過數學公式控制動畫,如勻速變化,先慢后快等效果。基於動畫函數的實現上,對各自展示節點的效果表現上,又封裝了三個函數做對應的處理。

 

數字飛升動畫效果實現的封裝函數為:

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);
        }
    });
}

而光柱的實現方式上也是與數字飛升的效果一樣,通過在隨機的范圍位置坐標內通過設定不同的時間差隨機生成,來形成與數字飛升為對立面的光柱下降效果,與線框建築的科技風格融為一體,很好地詮釋了整體風格的展示,這里對於光柱的動畫就不再多加贅述了。

 

相對應的是,停車場隨機停放的效果展示,不同於以上的動畫視覺展示,本身還是具有其效果意義的,可以對接真實的數據進行對整個停車場的車輛安放做可視化的數據維護和管理,而我們這里的實現上,則很好地模擬了這一事件的處理方式,也是通過一個簡單的封裝函數來體現停車場的動畫效果:

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);
        }
    });
}

 

三、機房的實現
機房的實現上,通過點擊機櫃轉移鎖定視角后展示機櫃的內部信息,並且虛化周圍設備的狀態,雙擊背景則會返回到初始的視角並且恢復默認狀態;其次,通過按鈕觸發顯示機櫃的利用率色塊展示,可以很全面地觀察到各個機櫃的內部消耗信息,方便整體機房的維護和管理。
在機櫃的點擊事件處理上,先使得整體的機房機櫃全部開啟透明並且降低透明度達到整體虛化的效果,然后通過點擊事件的處理,獲取到節點信息,此時運用到封裝好的開門動畫函數,開門后虛化掉這個機櫃的外殼后,顯示展示機櫃的內部設備信息;雙擊背景則恢復之前所做的效果處理操作,視角轉移到默認機房視角。
在點擊事件監聽后,通過 HT 封裝的視角轉移函數 flyTo() 鎖定到對應的機櫃:
  • direction:默認undefined,眼睛處於目標的方向(相對目標,受到目標自身旋轉影響),例如[0,1,5]在目標正面的斜向上;
  • animation:默認false,是否使用動畫,可以設置為true或者false或者animation動畫對象;
  • ratio:默認0.8,浮點類型,表示眼睛跟中心的距離動態計算(例如 0.8 表示眼睛在上述方向上動態計算距離以將目標包圍盒的8個角全部適配到屏幕80%范圍內);
g3d.flyTo(data, {
    direction: [0, 10, 10],
    animation: true,
    ratio: 0.9,
});

 

對於門的開啟動畫,首先是將門設置對應的機櫃為父節點,通過點擊事件的監聽處理后,根據多點擊的節點,將對應的門節點和旋轉角度信息,去調用門的封裝動畫函數:

// 傳入節點和旋轉角度信息
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),通過開啟動畫函數達到一種視角切換的過渡效果:

  • eye:相機位置坐標;
  • center:中心點位置坐標;
  • anim:默認 false,是否使用動畫,可以設置為true或者false或者animation動畫對象;
 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);
    })
}

 

總結
線框風格只是科技風格上效果展示的一種形態,HT 自身通過數年來的行業積累,總結出了許多的風格基調設定和對應的行業應用場合,加上自身豐富的組態化快速搭建上,順應工業互聯網的浪潮,可以推動實現許多行業上的解決方案,例如數字孿生的衍生,新基建的可視化系統等廣泛的行業上都有涉及,在多種多樣的行業領域上,相信 HT 一定帶你發掘不一樣的工業互聯網!
2019 我們也更新了數百個工業互聯網 2D/3D 可視化案例集,在這里你能發現許多新奇的實例,也能探索許多好玩的效果實現和工業互聯網的展示: https://mp.weixin.qq.com/s/ZbhB6LO2kBRPrRIfHlKGQA
同時,你也可以查看更多案例及效果: https://www.hightopo.com/demos/index.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM