婷婷综合国产,91蜜桃婷婷狠狠久久综合9色 ,九九九九九精品,国产综合av

主頁 > 知識庫 > 基于HTML5 WebGL的3D機房的示例

基于HTML5 WebGL的3D機房的示例

熱門標簽:成都智能外呼系統平臺 鎮江智能外呼系統有效果嗎 四川點撥外呼系統 南寧點撥外呼系統哪家公司做的好 江蘇智能電銷機器人哪家好 黃島區地圖標注 電銷機器人電話用什么卡 當涂高德地圖標注 云南大理400電話申請官方

前言

用 WebGL 渲染的 3D 機房現在也不是什么新鮮事兒了,這篇文章的主要目的是說明一下,3D 機房中的 eye 和 center 的問題,剛好在項目中用上了,好生思考了一番,最終覺得這個例子最符合我的要求,就拿來作為記錄。

效果圖

這個 3D 機房的 Demo 做的還不錯,比較美觀,基礎的交互也都滿足,接下來看看怎么實現。

代碼生成

定義類

首先從 index.html 中調用的 js 路徑順序一個一個打開對應的 js,server.js 中自定義了一個 Editor.Server 類由 HT 封裝的 ht.Default.def 函數創建的(注意,創建的類名 Editor.Server 前面的 Editor 不能用 E 來替代):

ht.Default.def('Editor.Server', Object, {//第一個參數為類名,如果為字符串,自動注冊到HT的classMap中;第二個參數為此類要繼承的父類;第三個參數為方法和變量的聲明
    addToDataModel: function(dm) { //將節點添加進數據容器
        dm.add(this._node);// ht 中的預定義函數,將節點通過 add 方法添加進數據容器中
    },
    setHost: function() { //設置吸附
        this._node.setHost.apply(this._node, arguments); 
    },
    s3: function() {//設置節點的大小
        this._node.s3.apply(this._node, arguments);
    },
    setElevation: function() {//控制Node圖元中心位置所在3D坐標系的y軸位置
        this._node.setElevation.apply(this._node, arguments);
    }
});

創建 Editor.Server 類

這個類可以創建一個 ht.Node 節點,并設置節點的顏色和前面貼圖:

var S = E.Server = function(obj) {//服務器組件
    var color = obj.color, 
        frontImg = obj.frontImg;

    var node = this._node = new ht.Node();//創建節點
    node.s({//設置節點的樣式 s 為 setStyle 的縮寫
        'all.color': color,//設置節點六面的顏色
        'front.image': frontImg //設置節點正面的圖片
    });
};

這樣我在需要創建服務器組件的位置直接 new 一個新的服務器組件對象即可,并且能夠直接調用我們上面聲明的 setHost 等函數,很快我們就會用上。

接下來創建 Editor.Cabinet 機柜類 ,方法跟上面 Editor.Server 類的定義方法差不多:

ht.Default.def('Editor.Cabinet', Object, {
    addToDataModel: function(dm) {
        dm.add(this._door);
        dm.add(this._node);
        this._serverList.forEach(function(s) { 
            s.addToDataModel(dm); 
        });
    },
    p3: function() { 
        this._node.p3.apply(this._node, arguments);//設置節點的 3d 坐標
    }
});

創建 Editor.Cabinet 類

這個類相對于前面的 Editor.Server 服務器組件類要相對復雜一點,這個類中創建了一個柜身、柜門以及機柜內部的服務器組件:

var C = E.Cabinet = function(obj) {
    var color = obj.color,
        doorFrontImg = obj.doorFrontImg,
        doorBackImg = obj.doorBackImg,
        s3 = obj.s3;

    var node = this._node = new ht.Node(); // 柜身
    node.s3(s3);//設置節點的大小 為 setSize3d
    node.a('cabinet', this);//自定義 cabinet 屬性
    node.s({//設置節點的樣式 為 setStyle
        'all.color': color,//設置節點六面的顏色
        'front.visible': false//設置節點前面是否可見
    });

    if (Math.random() > 0.5) {
        node.addStyleIcon('alarm', {//向節點上添加 icon 圖標
            names: ['icon 溫度計'],//包含多個字符串的數組,每個字符串對應一張圖片或矢量(通過ht.Default.setImage注冊)
            face: 'top',//默認值為front,圖標在3D下的朝向,可取值left|right|top|bottom|front|back|center
            position: 17,//指定icons的位置
            autorotate: 'y',//默認值為false,圖標在3D下是否自動朝向眼睛的方向
            t3: [0, 16, 0],//默認值為undefined,圖標在3D下的偏移,格式為[x,y,z]
            width: 37,//指定每個icon的寬度,默認根據注冊圖片時的寬度
            height: 32,//指定每個icon的高度,默認根據注冊圖片時的高度
            textureScale: 4,//默認值為2,該值代表內存實際生成貼圖的倍數,不宜設置過大否則影響性能
            visible: { func: function() { return !!E.alarmVisible; }}//表示該組圖片是否顯示
        });
    }

    var door = this._door = new ht.DoorWindow();//柜門
    door.setWidth(s3[0]);//置圖元在3D拓撲中的x軸方向的長度
    door.setHeight(1);//設置圖元在3D拓撲中的z軸長度
    door.setTall(s3[1]);//控制Node圖元在y軸的長度
    door.setElevation(0);//設置圖元中心在3D坐標系中的y坐標
    door.setY(s3[2] * 0.5);//設置節點在 y 軸的位置
    door.setHost(node);//設置吸附
    door.s({//設置節點樣式 setStyle
        'all.color': color,//設置節點六面顏色
        'front.image': doorFrontImg,//設置節點正面圖片
        'front.transparent': true,//設置節點正面是否透明
        'back.image': doorBackImg,//設置節點背面的圖片
        'back.uv': [1,0, 1,1, 0,1, 0,0],//自定義節點后面uv貼圖,為空采用默認值[0,0, 0,1, 1,1, 1,0]
        'dw.axis': 'right'//設置DoorWindow圖元展開和關閉操作的旋轉軸,可取值left|right|top|bottom|v|h
    });

    var serverList = this._serverList = []; 
    var max = 6,
        list = E.randomList(max, Math.floor(Math.random() * (max - 2)) + 2); //global.js 中聲明的獲取隨機數的函數 
    var server, h = s3[0] / 4;
    list.forEach(function(r) {
        var server = new E.Server({ //服務器組件
            color: 'rgb(51,49,49)',
            frontImg: '服務器 組件精細'
        });
        server.s3(s3[0] - 2, h, s3[2] - 4);//設置節點大小
        server.setElevation((r - max * 0.5) * (h + 2));//設置節點中心點在 y 軸的坐標
        server.setHost(node);//設置節點的吸附

        serverList.push(server);//向 serverList 中添加 server 節點
    });
};

上面代碼中唯一沒提到的是 Editor.randomList 函數,這個函數是在 global.js 文件中聲明的,聲明如下:

var E = window.Editor = {
    leftWidth: 0,
    topHeight: 40,
    randomList: function(max, size) {
        var list = [], ran;
        while (list.length < size) {
            ran = Math.floor(Math.random() * max);
            if (list.indexOf(ran) >= 0) 
                continue;
            list.push(ran);
        }
        return list;
    }
};

好了,場景中的各個部分的類都創建完成,那我們就該將場景創建起來,然后將這些圖元都堆進去!

場景創建

如果熟悉的同學應該知道,用 HT 創建一個 3D 場景只需要 new 一個 3D 組件,再將通過 addToDOM 函數將這個場景添加進 body 中即可:

var g3d = E.main = new ht.graph3d.Graph3dView(); //3d 場景

main.js 文件中主要做的是在 3D 場景中一些必要的元素,比如墻面,地板,門,空調以及所有的機柜的生成和排放位置,還有非常重要的交互部分。

墻體,地板,門,空調和機柜的創建我就不貼代碼出來了,有興趣的請自行查看代碼,這里主要說一下雙擊機柜以及與機柜有關的任何物體(柜門,服務器設備)則 3D 中 camera 的視線就會移動到雙擊的機柜的前方某個位置,而且這個移動是非常順滑的,之前技藝不精,導致這個部分想了很久,最后參考了這個 Demo 的實現方法。

為了能夠重復地設置 eye 和 center,將設置這兩個參數對應的內容封裝為 setEye 和 setCenter 方法,setCenter 方法與 setEye 方法類似,這里不重復贅述:

// 設置眼睛位置
var setEye = function(eye, finish) {
    if (!eye) return;
    var e = g3d.getEye().slice(0),//獲取當前 eye 的值
        dx = eye[0] - e[0],
        dy = eye[1] - e[1],
        dz = eye[2] - e[2];
    // 啟動 500 毫秒的動畫過度
    ht.Default.startAnim({
        duration: 500,
        easing: easing,//動畫緩動函數
        finishFunc: finish || function() {}, //動畫結束后調用的函數
        action: function(v, t) {//設置動畫v代表通過easing(t)函數運算后的值,t代表當前動畫進行的進度[0~1],一般屬性變化根據v參數進行
            g3d.setEye([ //設置 3D 場景中的 eye 眼睛的值,為一個數組,分別對應 x,y,z 軸的值 
                e[0] + dx * v,
                e[1] + dy * v,
                e[2] + dz * v
            ]);
        }
    });
};

我沒有重復聲明 setCenter 函數不代表這個函數不重要,恰恰相反,這個函數在“視線”移動的過程中起到了決定性的作用,上面的 setEye 函數相當于我想走到我的目標位置的前面(至少我定義的時候是這種用途),而 sCenter 的定義則是將我的視線移到了目標的位置(比如我可以站在我現在的位置看我右后方的物體,也可以走到我右后方去,站在那個物體前面看它),這點非常重要,請大家好好品味一下。

雙擊事件倒是簡單,只要監聽 HT 封裝好的事件,判斷事件類型,并作出相應的動作即可:

g3d.mi(function(e) {//addInteractorListener 事件監聽函數
    if (e.kind !== 'doubleClickData')  //判斷事件類型為雙擊節點
        return;
    var data = e.data, p3;

    if (data.a('cabinet')) //機身
        p3 = data.p3();
    else {
        host = data.getHost(); //獲取點擊節點的吸附對象
        if (host && host.a('cabinet')) {//如果吸附對象為 cabinet
            p3 = host.p3();
        }
    }

    if (!p3) return;

    setCenter(p3); //設置 center 目標的要移向位置為 cabinet 的位置
    setEye([p3[0], 211, p3[2] + 247]); //設置 eye 眼睛要移向的位置
});

頂部導航欄

一開始看到這個例子的時候我在想,這人好厲害,我用 HT 這么久,用 HT 的 ht.widget.Toolbar 還沒能做出這么漂亮的效果,看著看著發現這原來是用 form 表單做的,厲害厲害,我真是太愚鈍了。

var form = E.top = new ht.widget.FormPane(); //頂部 表單組件
form.setRowHeight(E.topHeight);//設置行高
form.setVGap(-E.topHeight);//設置表單組件水平間距 設置為行高的負值則可以使多行處于同一行
form.setVPadding(0);//設置表單頂部和頂部與組件內容的間距
form.addRow([null, {//向表單中添加一行組件,第一個參數為元素數組,元素可為字符串、json格式描述的組件參數信息、html元素或者為null
    image: {
        icon: './symbols/inputBG.json',
        stretch: 'centerUniform'
    }
}], [40, 260]);//第二個參數為每個元素寬度信息數組,寬度值大于1代表固定絕對值,小于等于1代表相對值,也可為80+0.3的組合
form.addRow([null, null, {
    id: 'searchInput',
    textField: {}
}, {
    element: '機房可視化管理系統',
    color: 'white',
    font: '18px arial, sans-serif'
}, null, {
    button: {
        // label: '視圖切換',
        icon: './symbols/viewChange.json',
        background: null,
        selectBackground: 'rgb(128,128,128)',
        borderColor: 'rgba(0, 0, 0, 0)',
        onClicked: function() {
            E.focusTo();
        }
    }
}, null, {
    button: {
        // label: '告警',
        icon: './symbols/alarm.json',
        togglable: true,
        selected: false,
        background: null,
        selectBackground: 'rgb(128,128,128)',
        borderColor: 'rgba(0, 0, 0, 0)',
        onClicked: function(e) {
            E.setAlarmVisible(this.isSelected());
        }
    }
}, null], [40, 42, 218, 300, 0.1, 50, 10, 50, 10]);

以上都只是能實現,但是并沒有真正地添加進 html 標簽中,也就意味著,現在界面上什么都沒有!別忘了在頁面加載的時候將 3D 場景添加進 body 中,同時也別忘了將 form 表單添加進 body 中,并且設置窗口大小變化事件時,form 表單也需要實時更新:

window.addEventListener('load', function() {
    g3d.addToDOM(); //將 3D 場景添加進 body 中

    document.body.appendChild(E.top.getView()); //將 form 表單組件底層 div 添加進 body 中

    window.addEventListener('resize', function() {//窗口大小變化事件監聽
        E.top.iv();//更新 form 表單的底層 div 
    });
});

這里說明一下 addToDOM 函數,對于了解 HT 的機制非常重要。HT 的組件一般都會嵌入 BorderPane、SplitView 和 TabView 等容器中使用,而最外層的 HT 組件則需要用戶手工將 getView() 返回的底層 div 元素添加到頁面的 DOM 元素中,這里需要注意的是,當父容器大小變化時,如果父容器是 BorderPane 和 SplitView 等這些 HT 預定義的容器組件,則 HT 的容器會自動遞歸調用孩子組件invalidate 函數通知更新。但如果父容器是原生的 html 元素, 則 HT 組件無法獲知需要更新,因此最外層的 HT 組件一般需要監聽 window 的窗口大小變化事件,調用最外層組件 invalidate 函數進行更新。

為了最外層組件加載填充滿窗口的方便性,HT 的所有組件都有 addToDOM 函數,其實現邏輯如下,其中 iv 是 invalidate 的簡寫:

addToDOM = function(){   
    var self = this,
        view = self.getView(),   
        style = view.style;
    document.body.appendChild(view); //將場景的底層 div 添加進 body 中           
    style.left = '0';//HT 默認將所有的組件底層div的position設置為absolute
    style.right = '0';
    style.top = '0';
    style.bottom = '0';      
    window.addEventListener('resize', function () { self.iv(); }, false); //窗口大小變化監聽事件,通知組件變化更新          
}

這樣,所有的代碼就結束了,可以自己右鍵“檢查”,network 中可以獲取相對應的 json 文件。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。

標簽:南京 佳木斯 淮安 咸寧 酒泉 十堰 廣西 西寧

巨人網絡通訊聲明:本文標題《基于HTML5 WebGL的3D機房的示例》,本文關鍵詞  基于,HTML5,WebGL,的,機房,;如發現本文內容存在版權問題,煩請提供相關信息告之我們,我們將及時溝通與處理。本站內容系統采集于網絡,涉及言論、版權與本站無關。
  • 相關文章
  • 下面列出與本文章《基于HTML5 WebGL的3D機房的示例》相關的同類信息!
  • 本頁收集關于基于HTML5 WebGL的3D機房的示例的相關信息資訊供網民參考!
  • 推薦文章
    婷婷综合国产,91蜜桃婷婷狠狠久久综合9色 ,九九九九九精品,国产综合av
    偷拍与自拍一区| 欧美国产精品劲爆| 精品一区二区三区视频| 亚洲狠狠丁香婷婷综合久久久| 日韩午夜在线观看视频| 国产午夜精品久久久久久久| 国产女主播视频一区二区| 亚洲国产精品黑人久久久| 国产精品青草久久| 国产精品嫩草久久久久| 91麻豆免费观看| 91麻豆国产精品久久| aa级大片欧美| 国产盗摄女厕一区二区三区| 蜜臀av国产精品久久久久| 风间由美中文字幕在线看视频国产欧美| 国产老妇另类xxxxx| 欧美日韩在线免费视频| 国产精品素人一区二区| 久久99这里只有精品| 9191成人精品久久| 一区二区三区高清不卡| 成人精品国产免费网站| 精品国产第一区二区三区观看体验 | 国产成人自拍网| 91麻豆国产福利精品| 欧美成人a∨高清免费观看| 中文字幕一区在线观看| 亚洲激情自拍视频| 91小视频在线免费看| 一区二区三区日本| 99久久伊人网影院| 中文字幕一区日韩精品欧美| 国产91在线观看| 国产人久久人人人人爽| 风间由美一区二区三区在线观看 | 性做久久久久久| 欧美高清视频www夜色资源网| 亚洲一区二区精品3399| 欧美优质美女网站| 婷婷国产在线综合| 久久久精品中文字幕麻豆发布| 亚洲综合激情网| 777色狠狠一区二区三区| 免费日韩伦理电影| 亚洲精品一区二区三区蜜桃下载 | 亚洲成人自拍网| 欧美色综合影院| 国产一区二区精品久久99| 精品国产一区二区亚洲人成毛片| 蜜臀av性久久久久av蜜臀妖精| 欧美日韩在线直播| 欧美日韩国产小视频| 亚洲综合一区在线| 中文字幕亚洲欧美在线不卡| 国产成人精品亚洲日本在线桃色| 亚洲电影欧美电影有声小说| 亚洲国产精品成人综合| 日韩欧美一区二区三区在线| 国产在线不卡一卡二卡三卡四卡| 国产精品色哟哟| 国产精品国模大尺度视频| 精品不卡在线视频| 久久精品欧美日韩精品| 久久午夜国产精品| 国产日韩成人精品| 国产精品三级av| 最新热久久免费视频| 国产成人在线视频免费播放| 久久精品国产澳门| 国产一区二区三区黄视频 | 91麻豆精品国产自产在线 | 亚洲色图视频网站| 亚洲免费观看高清完整| 国产欧美一区二区三区网站 | 日韩影院精彩在线| 亚洲欧美日韩在线不卡| 亚洲一区二区三区四区在线 | 天堂一区二区在线免费观看| 久久久99精品久久| 亚洲精选在线视频| 亚洲制服丝袜在线| 尤物在线观看一区| 狠狠色2019综合网| 欧美日韩五月天| 欧美一级久久久| 亚洲综合色自拍一区| 日韩av一区二区三区四区| 91行情网站电视在线观看高清版| 日韩一级成人av| 日韩欧美国产电影| 亚洲精品日韩综合观看成人91| 综合激情成人伊人| 日韩理论电影院| 国产综合色视频| 国产综合色精品一区二区三区| 成人av网站免费| 久久久久久亚洲综合影院红桃| 亚洲成av人片在线| 国产盗摄精品一区二区三区在线| 欧美男女性生活在线直播观看| 国产精品色哟哟| 国产女主播一区| 亚洲欧美日韩国产综合| 99久久婷婷国产综合精品| 国产精品久久久久久久久搜平片 | 欧美日韩mp4| 亚洲五月六月丁香激情| 色先锋aa成人| 亚洲国产精品视频| 在线综合视频播放| 日韩精品一级二级| 日韩欧美在线123| 国产一区二区三区四区五区美女| 欧美一激情一区二区三区| 麻豆免费精品视频| 国产亚洲精品福利| 欧美日韩一区精品| 蜜桃91丨九色丨蝌蚪91桃色| 91极品视觉盛宴| 蜜臀久久99精品久久久久久9| 久久久久久亚洲综合影院红桃| 日韩国产精品久久久| 99国产精品一区| 精品女同一区二区| 欧美视频在线观看一区二区| 国产精品一区二区无线| 香蕉久久一区二区不卡无毒影院| 91麻豆精品91久久久久久清纯| 国产麻豆一精品一av一免费| 亚洲欧美日本韩国| 欧美色综合天天久久综合精品| 国产xxx精品视频大全| 久久精品国产秦先生| 亚洲成在线观看| 欧美tickling挠脚心丨vk| 欧美色综合久久| 国产精品久线观看视频| 欧美亚洲综合一区| 日韩一区日韩二区| 成人午夜电影网站| 一区二区三区在线视频免费观看| 中文欧美字幕免费| 国产午夜精品久久久久久免费视 | 成人小视频免费在线观看| 国产乱色国产精品免费视频| 国产福利一区在线| 一本色道久久综合亚洲精品按摩| 成人a级免费电影| 在线视频国内一区二区| 欧美三级三级三级爽爽爽| 欧美一区二区三区爱爱| 亚洲国产综合在线| 99久久精品免费看| 中文字幕不卡的av| gogo大胆日本视频一区| 欧美一级一级性生活免费录像| 国产高清不卡一区二区| 一区二区三区四区国产精品| 亚洲欧洲无码一区二区三区| 精品久久久久久久久久久院品网| 99久久99久久免费精品蜜臀| 日韩二区三区在线观看| 久久久91精品国产一区二区三区| 午夜在线成人av| 国产精品动漫网站| 欧美一区二区三区四区视频| 欧美人动与zoxxxx乱| 91丝袜高跟美女视频| 不卡欧美aaaaa| 亚洲第一福利一区| 国产精品久久福利| 欧美高清在线一区二区| 精品国产网站在线观看| 宅男在线国产精品| 欧美日韩一级片网站| 一本大道久久a久久综合婷婷| 欧美xxx久久| 久久色视频免费观看| 久久久精品国产99久久精品芒果| 欧美片在线播放| 欧美久久久久久蜜桃| 天天影视色香欲综合网老头| 美女网站视频久久| 国产麻豆精品视频| 国产一区在线精品| 91久久精品一区二区| 色婷婷综合五月| 一区二区三区欧美久久| 欧美亚洲一区二区在线观看| 午夜影院久久久| 久久综合一区二区| 欧美中文一区二区三区| 麻豆精品一二三| 亚洲女与黑人做爰| 久久精品亚洲精品国产欧美| 欧美日韩大陆在线| 91福利资源站| 色综合久久综合| jvid福利写真一区二区三区|