基于 HTML5 WebGL 的 3D 服務器與客戶端的通信

這個例子的初衷是模擬服務器與客戶端的通信,我把整個需求簡化變成了今天的這個例子。3D 機房方面的模擬一般都是需要鷹眼來輔助的,這樣找產品以及整個空間的概括會比較明確,在這個例子中我也加了,這篇文章就算是我對這次項目的一個總結吧。對了,這個例子我是參考一個 DEMO 來完成的,和示例中的顯示有些不同,大家莫驚奇。

例子鏈接:?http://www.hightopo.com/demo/3DEdgeFlow/index.html

本文動圖:

這個例子沒有設計師的參與,樣式上面大家將就將就,但是我覺得還不錯啊,哈哈~

進入正題,整個例子差不多用了 200 行的代碼來實現的,這就是我喜歡用 HT 的原因,現在 Web3d 技術興起,大體就是分為兩派:插件派和 HTML5 派。HT 就是基于 HTML5 的,不需要安裝任何插件,啊,跑題了。。。

首先,還是從場景的搭建開始,這個界面是在 body 體上添加了三個部分:3d 組件,屬性組件以及拓撲組件(2d 組件)。添加的方式是這樣的:為了最外層組件加載填充滿窗口的方便性,HT?的所有組件都有 addToDOM 函數,其實現邏輯如下,其中 iv 是 invalidate 的簡寫:

addToDOM = function(){   var self = this,view = self.getView(),   style = view.style;document.body.appendChild(view);            style.left = '0';style.right = '0';style.top = '0';style.bottom = '0';      window.addEventListener('resize', function () { self.iv(); }, false);            
}

因為這個函數是將 style 中的位置都固定了,所以不能將所有的組件都用這個函數,我們按照這個函數的方式將拓撲組件和屬性組件添加進界面中,3d 組件直接利用 addToDOM 函數即可:

dm = new ht.DataModel();
g3d = new ht.graph3d.Graph3dView(dm);//3d 組件
g3d.addToDOM();//將組件添加進 body 體中
g3d.setDashDisabled(false);//開啟虛線流動
g3d.setMovableFunc(function(){//重載移動函數return false;//返回false,所有的圖元都不可移動
});
g3d.setEye([-813, 718, 1530]);//設置 eye 
g3d.setCenter([140, -25, 217]);//設置 center(target)
gv = new ht.graph.GraphView(dm);//2d 組件
gv.getView().className = 'graphview';//HT 組件根層都是一個 div,通過 getView() 函數獲取
document.body.appendChild(gv.getView());//將拓撲組件添加進 body 體中
gv.fitContent(true);//縮放平移整個拓撲以展示所有的圖元

propertyView = new ht.widget.PropertyView(dm);//屬性組件   
propertyView.getView().className = 'property';
propertyView.setWidth(240);//設置組件寬度
propertyView.setHeight(150);//高度
document.body.appendChild(propertyView.getView());

拓撲組件和屬性組件的樣式我就不再贅述了,只是設置了一個背景顏色以及 left right top bottom 位置而已。這里要聲明一下,HT 組件一般都以設置 position 為 absolute 的絕對定位方式。

大家可能會好奇,這個鷹眼怎么生成的?在 HT 中,只要 2D 和 3D 共用同一個數據容器 dataModel 即可共同擁有所有在這個 dataModel 中的元素,并且位置都是對應的,只需要類似這種做法即可:

dm = new ht.DataModel();
g3d = new ht.graph3d.Graph3dView(dm);
gv = new ht.graph.GraphView(dm);

是不是非常簡單。。。可以省去大把時間開發。。。

這個例子中除了連線之外的所有元素都是 ht.Node 類型的節點,所以我們將這個節點的創建方法封裝一下,好重復利用:

function createNode(p3, s3, name, shape){//創建節點var node = new ht.Node();//創建類型為 ht.Node 類的節點dm.add(node);//將節點添加進數據容器 dataModel 中node.s({//設置節點的樣式,s 為 setStyle 的簡寫'shape3d': shape,//指定節點的形體,這邊是傳入 3d 模型的 json 文件'label.position': 23,//文字顯示位置'label.transparent': true,//文字在3d下是否透明 可消除字體周圍的鋸齒'label.color': '#eee',//文字顏色'label.t3': [0, 0, -151],//文字在3d下的偏移'label.r3': [0, Math.PI, 0],//文字在3d下的旋轉'label.scale': 2//文字縮放
    });node.r3(0, Math.PI, 0);//節點旋轉node.p3(p3);//設置節點在 3d 下的位置node.s3(s3);//設置節點在 3d 下的大小node.setName(name);//設置節點的顯示名稱return node;//返回節點
}

以及連線的創建:

function createEdge(exchange, service){//創建連線var edge = new ht.Edge(exchange, service);dm.add(edge);edge.s({'edge.width': 4,//連線寬度'edge.color': 'red',//連線顏色'edge.dash': true,//是否顯示虛線'edge.dash.color': 'yellow',//虛線顏色'edge.dash.pattern': [32, 32],//連線虛線樣式默認為[16, 16]
    });edge.a({//用戶自定義屬性 為 setAttr 的縮寫'flow.enable': true,//是否啟用流動'flow.direction': 1,//方向'flow.step': 4//步進
    });return edge;
}

我們界面中的顯示的連線都是虛線流動的,HT 默認是關閉虛線流動的功能的,通過下面這句來開啟虛線流動的功能:

g3d.setDashDisabled(false);//開啟虛線流動

同時我們還需要設置動畫,控制時間間隔,使得連線虛線偏移,形成一種“流動”的狀態,動畫請參考 schedule 調度手冊:

flowTask = {interval: 40,action: function(data){if(data.a('flow.enable')){data.s('edge.dash.offset', data.s('edge.dash.offset')+(data.a('flow.step')*data.a('flow.direction')));}}
};
dm.addScheduleTask(flowTask);//添加flowTask動畫

以下是界面上出現的所有的服務器以及客戶端的節點的聲明,都是基于 createNode 和 createEdge 函數創建的:

floor = createNode([0, 5, 0], [1000, 10, 500]);//地板圖元
floor.s({//設置圖元的樣式 s 為 setStyle 的縮寫'all.color': 'rgb(47, 79, 79)'//六面體的整體顏色
});exchange = createNode([0, 300, -400], [200, 20, 150], 'H3C 核心交換機', 'models/機房/機柜相關/機柜設備6.json');//交換機//五臺不同作用的服務器
service1 = createNode([-400, 140, 0], [100, 260, 100], '備用', 'models/機房/機柜相關/機柜2.json');
service2 = createNode([-200, 140, 0], [100, 260, 100], '網站', 'models/機房/機柜相關/機柜2.json');
service3 = createNode([0, 140, 0], [100, 260, 100], 'OA', 'models/機房/機柜相關/機柜2.json');
service4 = createNode([200, 140, 0], [100, 260, 100], '廣告', 'models/機房/機柜相關/機柜2.json');
service5 = createNode([400, 140, 0], [100, 260, 100], '受理', 'models/機房/機柜相關/機柜2.json');//創建交換機與服務器之間的連線
createEdge(exchange, service1);
createEdge(exchange, service2);
createEdge(exchange, service3);
createEdge(exchange, service4);
createEdge(exchange, service5);
//第二臺交換機
exchange2 = createNode([-100, 60, 400], [200, 20, 150], 'Procurve Switch 2010-23 交換機', 'models/機房/機柜相關/機柜設備6.json').s('label.color', '#000');createEdge(exchange2, service1);
createEdge(exchange2, service2);
createEdge(exchange2, service3);
createEdge(exchange2, service4);
createEdge(exchange2, service5);floor2 = createNode([-100, 5, 800], [1000, 10, 500]);
floor2.s({'all.color': 'rgb(47, 79, 79)'
});device1 = createNode([-400, 20, 650], [200, 20, 100], 'VLS 12000(上)', 'models/機房/機柜相關/機柜設備6.json');
device2 = createNode([100, 20, 650], [200, 20, 100], 'VLS 12000(下)', 'models/機房/機柜相關/機柜設備6.json');
device3 = createNode([-200, 20, 800], [200, 20, 100], 'HP Strage Works 8/8 SAN Switch(上)', 'models/機房/機柜相關/機柜設備6.json');
device4 = createNode([200, 20, 800], [200, 20, 100], 'HP Strage Works 8/8 SAN Switch(下)', 'models/機房/機柜相關/機柜設備6.json');
device5 = createNode([-300, 20, 950], [200, 20, 100], 'EVA 8400 HSV450(上)', 'models/機房/機柜相關/機柜設備6.json');
device6 = createNode([100, 20, 950], [200, 20, 100], 'EVA 8400 HSV450(下)', 'models/機房/機柜相關/機柜設備6.json');createEdge(exchange2, device1);
edge1 = createEdge(exchange2, device2);
createEdge(device1, device3);
createEdge(device1, device4);
createEdge(device2, device3);
createEdge(device2, device4);
createEdge(device3, device5);
createEdge(device3, device6);
createEdge(device4, device5);
createEdge(device4, device6);
dm.sm().ss(edge1);//設置選中 edge1

最后,需要在屬性欄中添加屬性,這里我們只對“連線”進行了屬性的顯示及調整,總共 5 個屬性,包括我通過 setAttr(簡寫為 a)自定義的屬性 flow.enable、flow.direction、flow.step 和樣式屬性 edge.color 以及 edge.dash.color。我們通過 name 屬性結合 accessType 屬性實現對 Data 節點的存取:

?

?

//連線的屬性
edgeProperties = [{name: 'flow.enable',//用于存取 name 屬性accessType: 'attr',//操作存取屬性類型displayName: 'Enable Flow',//用于存取屬性名的顯示文本值,若為空則顯示 name 屬性值valueType: 'boolean',//用于提示組件提供合適的 renderer 渲染,boolean 類型,顯示為勾選框editable: true//設置該屬性是否可編輯
    },{name: 'flow.direction',accessType: 'attr',displayName: 'Flow Direction',enum: {//枚舉類型屬性 傳遞數值和文字數組values: [-1, 1],labels: ['正向流動', '反向流動']},editable: true},{name: 'flow.step',displayName: 'Flow Step',                        editable: true,accessType: 'attr',slider: {//表單插件中的滑動條 所以要添加 ht-form.js min: 0,//最小值max: 10,//最大值step: 0.1//步進
        }},{name: 'edge.color',accessType: 'style',displayName: 'Edge Color',editable: true,valueType: 'color',//顏色類型,以填充背景色的方式顯示colorPicker: {//顏色選擇框instant: true//獲取和設置是否處于即時狀態,默認為true,代表作為表格和屬性頁的編輯器時,將實時改變模型值
        }},{name: 'edge.dash.color',displayName: 'Dash Color',accessType: 'style',valueType: 'color',editable: true,colorPicker: {instant: true}}
];
propertyView.setEditable(true);//設置屬性組件可編輯
propertyView.addProperties(edgeProperties);//添加連線屬性

是不是非常簡單~? 快動手實踐一下吧!

轉載于:https://www.cnblogs.com/xhload3d/p/8124629.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/453247.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/453247.shtml
英文地址,請注明出處:http://en.pswp.cn/news/453247.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

什么是順序執行以及其特點

順序執行是程序的一種執行方式。是把一個具有獨立功能的程序獨占處理機直至最終結束的過程稱為程序的順序執行 順序執行的特點:順序性:程序順序執行時,其執行過程可看作一系列嚴格按程序規定的狀態轉移過程,也即是每執行一條指令&…

一年成為Emacs高手(像神一樣使用編輯器)

作者: 陳斌(redguardtoo) 更新時間: 2012-02-10 五 原創時間: 2012-01-31 周二 15:08 很容易.一年多前我還在Vi陣營,偶爾使用Emacs還總是忘記退出(C-x C-c)的快捷鍵,但是一年后我跨入高手行列. 現在網上很多中文文章都是和你強調Emacs有多牛,以激發你的興趣.最有名的大概是王垠…

七種常見的核酸序列蛋白編碼能力預測工具 | ncRNAs | lncRNA

注:這些工具的應用都是受限的,有些本來就是只能用于預測動物,在使用之前務必用ground truth數據來測試一些。我想預測某一個植物的轉錄本,所以可以拿已經注釋得比較好的擬南芥來測試一下。(測試的結果還是比較驚人的&a…

android預覽界面編譯出錯,Android O預覽findViewById編譯錯誤

我試圖測試Android O Developer Preview的第二階段。 項目創建后,我只是點擊了構建并運行但我沒有任何成功。Android默認生成的代碼如下:Toolbar toolbar (Toolbar) findViewById(R.id.toolbar);發生編譯錯誤。Error:(18, 37) error: reference to find…

中斷與異常的區別

中斷: 中斷是CPU(硬件)所具備的功能 ,它是指系統停止當前正在運行的程序而轉向其他服務,可能是因 為優先級高的請求服務了,或者是因為人為安排中斷。中斷是屬于正常現象。主要由CPU以外的事件引起的 中斷…

寒武紀找到了引領中國AI芯片走向世界的路

大約6億年前在地質學上被稱作“寒武紀”的時代,大量無脊椎動物在短時間內出現“生命大爆發”。如今,“寒武紀”這個名字再次被人們提及,它源自中科院計算所研發的人工智能芯片處理器的命名,意喻人工智能即將迎來大爆發的時代。“寒…

淺談PPM (Project Portfolio Management)

前言: 本文以純理論性的PPM講解為主,不會涉及到具體如何實施,我會在以后介紹詳細的PPM實施方案介紹。 PPM,可能很多人并不清楚甚至可能沒聽說過,這是一個近些年才流行起來的概念,是Project Portfolio Mana…

poj 3071 Football

http://poj.org/problem?id3071 2^n 支足球隊比賽,共比n場,第一場1號與2號比,3號與4號比…… 每場勝出者進入下一場,輸者淘汰 每一場都是相鄰的兩個隊伍比拼 已知任意兩個隊伍比拼獲勝的概率 求最后哪只隊伍獲勝的概率最大 dp[i]…

進程調度與作業調度

進程調度是真正讓某個就緒狀態的進程到處理機上運行,而作業調度只是使作業具有了競爭處理機的機會。進程調度(又稱微觀調度、低級調度、短程調度): 是按照某種調度算法從就緒狀態的進程中選擇一個進程到處理機上運行。負責進程調…

tensorflow源碼安裝

主要參考:https://www.tensorflow.org/install/install_sources#ConfigureInstallation卸載tensorflow sudo pip uninstall tensorflow 安裝git 安裝git時記得先安裝,后更新系統 sudo apt install git安裝jdk8: myubuntu:~$ java myubun…

Makefile學習之通配符和自動變量

規則中的通配符 “*” ,“?” ,“ [...]”, " % " , " wildcard " 1.“*” *.c表示所有后綴為.C的文件; 如果文件中用到通配符,使用“\*”; 2.通配符在變量中的使用; objects*.c 注意…

英語中十二個月名稱的由來

轉自網絡,原出處不詳。 公歷一年有12個月,但不少人并不知道12 個月的英語名稱的來歷。公歷起源于古羅馬歷法。羅馬的英語原來只有10 個月,古羅馬皇帝決定增加兩個月放在年尾,后來朱里斯*凱撒大帝把這兩個月移到年初,…

進程和程序的關系

1 進程是一個動態概念,而程序是一個靜態概念。 2 進程具有并行特征,程序沒有。 3 進程是競爭資源的基本單位。 4 一個程序對應多個進程,一個進程為多個程序服務。

Android怎么插手機卡,魅藍E手機卡怎么裝 魅藍E手機SIM卡安裝圖文教程

昨天下午,魅族發布了全新系列魅藍手機——魅藍E,定位魅藍高端產品線,售價1299元,李楠號稱魅藍E采用三四千元的旗艦機工藝,外觀/屏幕/拍照提升明顯。此外,魅藍E依舊支持全網通雙卡雙待。那么魅藍E怎么插卡/裝…

快速冪總結

快速冪總結 快速冪這個東西比較好理解,但實現起來到不老好辦,記了幾次老是忘,今天把它系統的總結一下防止忘記。 首先,快速冪的目的就是做到快速求冪,假設我們要求a^b,按照樸素算法就是把a連乘b次,這樣一來…

第三章

一.項目前期的主要工作 1.現狀分析 ①.硬件分析 ②.軟件分析 2.需求收集 3.粗略設計 ①.體系結構分析 ②.硬件(網絡)設計 ③.應用系統設計 ④.安全設計 ⑤.配套設計 4.可行性分析 二.結構的項目前期實例 1.組織分析 3.需求收集 4.粗略設計 ①.系統體系結…

進程的靜止和活動狀態

進程有3個主要狀態,即就緒,執行和等待。當一個進程被創建的時候,處于就緒狀態,嚴格地說是靜止就緒狀態,等到被激活,該進程就處于活動就緒狀態,如果時間片輪到該進程,那么該進程就執行…

榮耀magic3會用鴻蒙,趙明:榮耀Magic3芯片領先行業,大家看到以后會換掉手機!...

榮耀CEO趙明親自參加高通2021技術峰會,宣布與高通達成戰略合作,未來全系產品采用高通平臺。趙明同時透露未來的產品動向,不排除未來與華為繼續合作,采用鴻蒙操作系統的可能。趙明表示,Android操作系統依舊是榮耀的首選…

公司里從員工到經理,不同層級應該關注的事情

最近在看《領導梯隊》,超級棒的一本書,受益匪淺,推薦給各位從事管理方向的朋友 第一階段:從管理自我到管理他人(leader級)   新員工工作的最初幾年是個人貢獻者。無論他們從事的是銷售、會計、工程或是市…

繼續教育學習腳本

/* 本腳本運行于瀏覽器conlose中,自動點擊“繼續學習”按鈕,以實現阻止視頻的暫停 */ (function(){ var getStylefunction(obj,styleName){ if(obj.style){ return obj.style[styleName]; }else if(obj.currentStyle){ …