前言
這次為大家展示的是通過 HT for Web 靈活的圖型化編輯工具打造的智慧隧道監控系統。通過 HTML5 技術實現了桌面和移動端的跨平台性,同時現實了可視化運維。
這次主要跟大家分享里面的漫游巡檢功能,完美進行第一人稱視角體驗整體結構環境,酷似游戲一樣給人一種真實的感受,比平面更加直觀,隨意游離與虛擬和現實之間。
代碼實現
整個場景是由 3D 組件搭建而成的,需要大量的代碼,為了簡化,我用 HT 封裝的 ht.JSONSerializer 來將場景序列化為一個 json 文件。在代碼中,再通過 DataModel 數據模型反序列化,就是將 json 格式轉化為對象並添加到數據模型中。可參考序列化手冊。
我已經搭建好了場景,但是其中包含重要的一點就是我們在構建過程中一定要制作一條線來作為路徑基礎,這個我們稍后用到。
首先我們先記錄一下整體場景的初始視角,以便於我們在結束漫游后可以恢復視角:
var dm = new ht.DataModel(); var g3d = new ht.graph3d.Graph3dView(dm) var aEye = ht.Default.clone(g3d.getEye()) var aCenter = ht.Default.clone(g3d.getCenter())
為了避免在漫游的過程中在視角運動上出現 bug 我們先將交互器關掉。3D 交互器是什么呢?默認 Graph3dView 提供的是圍繞 Graph3dView#getCenter() 中心點旋轉的操作模式,這種模式下進行 Drag 操作時會改變 Graph3dView#getEye() 的眼睛觀察點位置,鼠標滾輪或觸屏 pinch 縮放的效果,實質上也是改變 eye 的位置,使其更接近或者遠離 center 中心位置,最終達到視覺縮放或者走近和遠離物體的效果。因為在進入漫游時不允許其它操作來干涉進行,所以要先處理掉:
g3d.setInteractors(null)
要移動,肯定要走我們在場景中畫的隱藏的線來做路徑:
var point1 = path.getPoints().toArray()[0] var point2 = path.getPoints().toArray()[3]
通過控制路徑中前后兩點來設置 3D 場景中的 eye 和 center,這樣就能營造出第一人稱視角效果:
var distanceX = (point1.x - point2.x) var distanceY = (point1.y - point2.y) // 兩點之間的距離通過三角形勾股定理計算 var distance = Math.sqrt(distanceX * distanceX + distanceY * distanceY) // 眼睛的位置 g3d.setEye([point2.x, 800, point2.y]) // "我"的位置 g3d.setCenter([point1.x, 800, point1.y])
這里我們將用到一個 walk 方法,它能夠同時改變 eye 和 center 的位置,也就是 eye 和 center 在兩點建立的矢量方向上同時移動相同的偏移量。第一個參數為偏移的矢量長度值,結束時恢復交互器並清空動畫:
var anim = g3d.walk(distance, { frames:700, finishFunc: function () { g3d.setEye(aEye) g3d.setCenter(aCenter) g3d.setInteractors([ mapInteractor ]) anim = null } }, true)
之前關閉交互器還有一個原因就是在漫游過程中我們還要有相關操作,先監聽鼠標滾輪事件,通過滾動來改變速度,向上加速,向下減速:
g3d.getView().addEventListener('mousewheel', function (e) { if (anim) { let detail = 0 if (!e) e = g3d.getView().e if (e.wheelDelta) { detail = e.wheelDelta/120 } else if (e.detail) { detail = -e.detail/3 } if (detail) // 改變速度 if (detail < 0) { // 向下滾動 if (anim.frames < 2000) { anim.frames += 50 } } else { // 向上滾動 if (anim.frames > 100) { anim.frames -= 50 } } } })
再監聽點擊事件來實現暫停、繼續和退出:
g3d.getView().addEventListener('mousedown', function (e) { if (anim) { if (e.button === 0) { // 左鍵暫停 anim.pause() }else if (e.button === 2){ // 右鍵繼續 anim.resume() }else if(e.button === 1){ // 中鍵退出 anim.stop() anim = null } } })
至此,漫游功能的實現代碼解釋完畢,很短的代碼量,卻做出了這么大的工程!
總結
同樣也有很多包含這個功能模塊的例子,都有着不錯的效果:
機房(http://www.hightopo.com/demo/room-walkthrough/index.html)
地鐵站(http://www.hightopo.com/demo/ht-subway/index.html)等等都是很好的。
從工業互聯網到產業互聯網,越來越多的智能化監控系統,運維系統,收費管理系統等其他業務系統應接不暇的出現,這些都是跟我們生活緊密相連的,都可以用信息化的方式來表達,HT 的輕量化與之相結合更好的展現出數據可視化的優勢。比如我們這次介紹的關於隧道的就是明顯的例子,還有橋梁公路,高鐵動車,乃至交通運輸領域,都被廣泛應用着。隨着時代的進步和前端 HTML5、WebGL、WebVR 等技術的成熟,相信 Web 承擔越來越重度的渲染呈現應用是不可逆的趨勢!