国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 編程 > HTML > 正文

HTML5 WebGL 實(shí)現(xiàn)民航客機(jī)飛行監(jiān)控系統(tǒng)

2024-08-26 00:21:35
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

前言

前些日子出差,在飛機(jī)上看到頭頂?shù)谋O(jiān)控面板,除了播放電視劇和廣告之外,還會(huì)時(shí)不時(shí)的切換到一個(gè)飛機(jī)航行的監(jiān)控系統(tǒng),不過(guò)整個(gè)監(jiān)控系統(tǒng)讓人感到有一點(diǎn)點(diǎn)的簡(jiǎn)陋,所以我就突發(fā)奇想制作了一個(gè)采用 HT for Web 的升級(jí)版監(jiān)控系統(tǒng),demo 的效果還行,發(fā)出來(lái)大家相互學(xué)習(xí)下。

HTML5,WebGL,飛行監(jiān)控系統(tǒng)
 

demo

實(shí)現(xiàn)過(guò)程

云中穿行效果

為了達(dá)到飛機(jī)云中穿行的效果,最開(kāi)始我遇到的問(wèn)題是飛機(jī)飛行的層次感,也就通常所說(shuō)的透視效果,這里我采用的是云通道和云背景以不同的速度流動(dòng),制造一種飛行的透視效果。

云我采用的是貼圖的方式呈現(xiàn)的,但是僅僅是貼圖會(huì)遮擋天空和飛機(jī),非常影響飛機(jī)飛行的觀感,所以我開(kāi)啟了相應(yīng)圖元的 transparent 和 opacity ,云背景和云通道設(shè)置不同的透明度,不僅增加了層次感,還會(huì)讓人產(chǎn)生云朵從眼前飄過(guò)的錯(cuò)覺(jué)。

云通道采用的是 ht.Polyline 類(lèi)型,通道縮放拉大了 Y 軸的比例,使云通道有更大的縱向空間,設(shè)置 reverse.flip 背拷貝使云通道內(nèi)部也顯示出貼圖,仿佛讓飛機(jī)置身于云海中穿梭;云背景采用 ht.Node 類(lèi)型,只設(shè)置一個(gè)面顯示充當(dāng)云背景。

整體的云流動(dòng)效果采用 offset 偏移實(shí)現(xiàn),改變相應(yīng)圖元或相應(yīng)圖元面的貼圖偏移量來(lái)達(dá)到飛機(jī)云中穿行的效果, 代碼如下:
 

var i = 1,     p = 0;setInterval(() => {    i -= 0.1; p += 0.005;    clouds.s('shape3d.uv.offset', [i, 0]);    cloudBackground.s('all.uv.offset', [p, 0]);}, 100);

升降顛簸效果

雖然達(dá)到了飛機(jī)云中穿行的效果,但是如果飛機(jī)只是直直的飛行,那也會(huì)降低飛行的實(shí)感,相信坐過(guò)飛機(jī)的朋友肯定都遇到過(guò)因氣流產(chǎn)生的顛簸,也經(jīng)常感受到飛機(jī)飛行途中的爬升和下降,這其實(shí)是因?yàn)轱w機(jī)的航線并不是一直固定在一個(gè)高度上,有時(shí)會(huì)爬升有時(shí)會(huì)下降,所以我就用 ht-animation.js HT 動(dòng)畫(huà)擴(kuò)展插件去實(shí)現(xiàn)飛機(jī)顛簸效果,代碼如下:

dm.enableAnimation(20);plane.setAnimation({    back1: {        from: 0,        to: 160,        easing: 'Cubic.easeInOut',        duration: 8000,        next: "up1",        onUpdate: function (value) {            value = parseInt(value);            var p3 = this.p3();            this.p3(value, p3[1], p3[2]);        }    },    //...省略相似    start: ["back1"]});

球扇形視角限制

飛行效果完善之后,這時(shí)我就遇到了一個(gè)比較棘手的問(wèn)題,因?yàn)閷?shí)際上雖然看著飛機(jī)是在云海中穿梭,但是僅僅是在通道中飛行,背景其實(shí)也只是平面貼圖,所以當(dāng)視角到達(dá)某種程度的時(shí)候就會(huì)有強(qiáng)烈的違和感和不真實(shí)感,就需要一個(gè)視角限制,使視角的調(diào)整剛剛好在一個(gè)范圍內(nèi)。

視角限制的話一般是限制 g3d 的 eye 和 center ,不太了解的朋友可以去看 hightopo 官網(wǎng)中的 3d 手冊(cè),里面有詳細(xì)的說(shuō)明,這里我就不再贅述了;因?yàn)橐暯欠秶年P(guān)系,所以我決定固定 center 的位置,代碼如下:
 

g3d.addPropertyChangeListener(e => {    // 固定中心點(diǎn)    if (e.property === 'center') {        e.newValue[0] = center[0];        e.newValue[1] = center[1];        e.newValue[2] = center[2];    }}

然后再把 eye 限制在某一個(gè)范圍內(nèi)就大功告成了,然而這里卻并不是那么簡(jiǎn)單,最開(kāi)始我把 eye 限制在一個(gè)立方體的空間內(nèi),但交互效果很不理想,考慮到 g3d 默認(rèn)交互中,鼠標(biāo)拖拽平移視角變換時(shí),實(shí)際上 eye 是在一個(gè)以 center 為球心的球面上運(yùn)動(dòng)的,所以我決定從這個(gè)球中挖出來(lái)一塊作為 eye 的限制空間,也就是球扇形,不太理解的朋友可以參考這個(gè)圖:

HTML5,WebGL,飛行監(jiān)控系統(tǒng)
 

球扇形視角限制,一共需要三個(gè)參數(shù),分別是中心參考軸、中心軸和外邊所成角度、所在球限制半徑,其中中心參考軸可根據(jù)初始 eye 和 center 的連接延長(zhǎng)線確定,所在球限制半徑又分最大限制和最小限制,代碼如下:

 

function limitEye(g3d, eye, center, options) {    var limitMaxL   = options.limitMaxL,        limitMinL   = options.limitMinL,        limitA      = options.limitA;    g3d.addPropertyChangeListener(e => {        // 固定中心點(diǎn)        if (e.property === 'center') {            e.newValue[0] = center[0];            e.newValue[1] = center[1];            e.newValue[2] = center[2];        }        // 限制視角        if (e.property === 'eye') {            var newEyeV = new ht.Math.Vector3(e.newValue),                centerV = new ht.Math.Vector3(center),                refEyeV = new ht.Math.Vector3(eye),                refVector = refEyeV.clone().sub(centerV),                newVector = newEyeV.clone().sub(centerV);            if (centerV.distanceTo(newEyeV) > limitMaxL) {                newVector.setLength(limitMaxL);                e.newValue[0] = newVector.x;                e.newValue[1] = newVector.y;                e.newValue[2] = newVector.z;            }            if (centerV.distanceTo(newEyeV) < limitMinL) {                newVector.setLength(limitMinL);                e.newValue[0] = newVector.x;                e.newValue[1] = newVector.y;                e.newValue[2] = newVector.z;            }            if (newVector.angleTo(refVector) > limitA) {                var oldLength = newVector.length(),                    oldAngle  = newVector.angleTo(refVector),                    refLength = oldLength * Math.cos(oldAngle),                    vertVector,                    realVector,                    realEye;                refVector.setLength(refLength);                newEyeV = newVector.clone().add(centerV);                refEyeV = refVector.clone().add(centerV);                vertVector = newEyeV.clone().sub(refEyeV);                vertLength = refLength * Math.tan(limitA);                vertVector.setLength(vertLength);                realVector = vertVector.clone().add(refEyeV).sub(centerV);                realVector.setLength(oldLength);                realEye = realVector.clone().add(centerV);                // 防止移動(dòng)角度大于 180 度,視角反轉(zhuǎn)                if (oldAngle > Math.PI / 2) {                    realEye.negate();                }                e.newValue[0] = realEye.x;                e.newValue[1] = realEye.y;                e.newValue[2] = realEye.z;            }          }    })}

HTML5,WebGL,飛行監(jiān)控系統(tǒng)

飛機(jī)監(jiān)控系統(tǒng)

當(dāng)然作為監(jiān)控系統(tǒng),自然要有監(jiān)控了,增加右下角的小地圖,并提供三種模式,分別是聚焦飛機(jī),聚焦飛行軌跡和聚焦地圖,并根據(jù)飛機(jī)的飛行方向控制飛行軌跡的流動(dòng)效果,其中聚焦飛機(jī)會(huì)跟隨飛機(jī)移動(dòng)進(jìn)行 fitData ,使飛機(jī)一直處于小地圖的中心,代碼如下:

 

var fitFlowP = function (e) {    if (e.property === 'position' && e.data === plane) {        mapGV.fitData(plane, false);    }};buttonP.s({    'interactive': true,    'onClick': function (event, data, view, point, width, height) {        map.a('fitDataTag', 'plane2D');        mapGV.fitData(plane, false);        mapDM.md(fitFlowP);    }});buttonL.s({    'interactive': true,    'onClick': function (event, data, view, point, width, height) {        mapDM.umd(fitFlowP);        map.a('fitDataTag', 'flyLine');        mapGV.fitData(flyLine, false);    }});// ...省略

HTML5,WebGL,飛行監(jiān)控系統(tǒng)

增加鼠標(biāo)移到飛機(jī)相應(yīng)位置進(jìn)行名稱(chēng)的提示、雙擊后顯示飛機(jī)相應(yīng)位置的信息面板并將視角聚焦到面板上、點(diǎn)擊飛機(jī)任意地方切換回飛機(jī)飛行模式等效果。

HTML5,WebGL,飛行監(jiān)控系統(tǒng)
 

左側(cè)增加監(jiān)控面板替代上面提到的雙擊相應(yīng)位置這步操作直接聚焦到相應(yīng)位置的信息面板上,這里按鈕開(kāi)啟了交互并添加了相應(yīng)的交互邏輯,代碼如下:

 

button_JC.s({    'interactive': true,    'onClick': function (event, data, view, point, width, height) {        event.preventDefault();        let g3d = G.g3d,            g3dDM = G.g3d.dm();        g3d.fireInteractorEvent({            kind: 'doubleClickData',            data: g3dDM.getDataByTag(data.getTag())        })    }});//...省略

HTML5,WebGL,飛行監(jiān)控系統(tǒng)

天空渲染效果

既然是監(jiān)控系統(tǒng)肯定是 24 小時(shí)無(wú)差別的監(jiān)控,這就涉及到一個(gè)問(wèn)題,我總不可能半夜的時(shí)候飛機(jī)也從瓦藍(lán)瓦藍(lán)的天空上飛過(guò),這就很欠缺真實(shí)性了,所以要有一個(gè)天空從亮到暗再?gòu)陌档搅恋倪^(guò)程,這個(gè)過(guò)程我暫定到 06:00-06:30 和19:00-19:30 這兩個(gè)時(shí)間段。

天空采用的是 shape3d : 'sphere' 球形,包裹整個(gè)場(chǎng)景,然后使用 reverse.flip 背拷貝 和 blend 染色,之后天空就可以渲染成我想要的顏色,如果按照時(shí)間改變天空明暗只要改變?nèi)旧稻涂梢粤恕?/p>

但是由于白天和晚上光照情況的不同,云反射光的強(qiáng)度也不同,就導(dǎo)致了白天和晚上云的差異,所以也要調(diào)整云道和云背景的貼圖的 opacity 透明度,晚間更為透明度,代碼如下:

if ((hour > 6 && hour < 19) || (hour == 6 && minutes >= 30)) {    timePane && timePane.a({        'morning.visible': false,        'day.visible': true,        'dusk.visible': false,        'night.visible': false,        'day.opacity': 1    })    skyBox.s({        "shape3d.blend": 'rgb(127, 200, 240)',    })    cloudBackground.s({        "back.opacity": 0.7,    })    clouds.s({        "shape3d.opacity": 0.7,    })} else if ((hour < 6 || hour > 19) || (hour == 19 && minutes >= 30)) {//...省略} else if (hour == 6 && minutes < 15 ) {//...省略} else if (hour == 6 && minutes >= 15 && minutes < 30) {//...省略} else if (hour == 19 && minutes < 15) {//...省略} else if (hour == 19 && minutes >= 15 && minutes < 30) {//...省略}

HTML5,WebGL,飛行監(jiān)控系統(tǒng)

這里我還增加了對(duì)右上角時(shí)間面板時(shí)間狀態(tài)圖標(biāo)的支持,并增加了圖標(biāo)切換時(shí)的漸隱漸顯效果,同時(shí)給時(shí)間面板狀態(tài)圖標(biāo)位置增加了點(diǎn)擊切換到下一時(shí)間狀態(tài)的功能。

為了演示效果我增加了時(shí)間倍速按鈕,下圖是 500 倍時(shí)間流速下的變化情況:

HTML5,WebGL,飛行監(jiān)控系統(tǒng)
 

總結(jié)

通過(guò)這個(gè) demo ,我發(fā)現(xiàn)生活中有很多沒(méi)有被人所注意到的細(xì)節(jié)都存在數(shù)據(jù)可視化的可能,在這個(gè)大數(shù)據(jù)的時(shí)代更多的可能性值得被人發(fā)掘出來(lái),不要錯(cuò)個(gè)身邊每一個(gè)值得數(shù)據(jù)可視化的細(xì)節(jié),這樣不僅可以更好的挖掘 HT for Web 的潛力,也可以加強(qiáng)自身身為一個(gè)程序員的綜合素質(zhì)。


注:相關(guān)教程知識(shí)閱讀請(qǐng)移步到HTML教程頻道。
發(fā)表評(píng)論 共有條評(píng)論
用戶(hù)名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 三门峡市| 桂林市| 静安区| 邵阳市| 本溪| 隆安县| 南乐县| 晋江市| 维西| 合作市| 麻栗坡县| 泰和县| 杭锦后旗| 龙州县| 辽宁省| 灌阳县| 宜宾市| 娄烦县| 梅河口市| 冷水江市| 乌恰县| 体育| 宜兴市| 黎川县| 西平县| 孟津县| 开化县| 翁牛特旗| 灵石县| 江达县| 凌云县| 黑河市| 昭觉县| 泰来县| 柘荣县| 上思县| 凭祥市| 鸡东县| 攀枝花市| 耿马| 华亭县|