文章目錄
- 參考
- 描述
- 界面自适應
-
-
- 問題
- resize 事件
- 修改畫布大小
- 修改視錐體的寬高比
-
- 全屏顯示
-
-
- dblclick 事件
- 檢測全屏顯示狀态
- 進入全屏顯示狀态
- 退出全屏顯示狀态
-
- 尾聲
參考
項目 | 描述 |
---|---|
ThreeJS | 官方文檔 |
哔哩哔哩 | 老陳打碼 |
搜尋引擎 | Bing |
MDN 文檔 | document.mozFullScreenElement |
MDN 文檔 | Element.requestFullscreen() |
MDN 文檔 | Document.exitFullscreen() |
描述
項目 | 描述 |
---|---|
npm | 8.19.3 |
node | v16.19.0 |
Edge | 110.0.1587.41 (正式版本) (64 位) |
ThreeJS | 0.148.0 |
webpack | 5.75.0 |
webpack-cli | 5.0.1 |
注:
在觀察本篇部落格後續内容前請先搭建 ThreeJS 運作的相關環境,如還未搭建相關環境,請移步至我的另一篇部落格 初識 ThreeJS (ThreeJS 相關環境搭建)。
界面自适應
問題
若你未為 ThreeJS 項目設定界面自适應功能,可能會産生如下問題:
在畫布建立完成後,改變視窗大小并不會對畫布(尺寸)産生影響,于是産生了上圖中的空白部分。
resize 事件
當浏覽器視口(浏覽器的可視區域)發生改變時将觸發 Window 對象的 resize 事件。我們可以在該事件對應的事件處理函數中實作界面自适應功能。
// 為 window 對象添加監聽器以監聽 resize 事件
window.addEventListener('resize', () => {
// 在此處實作界面自适應功能
})
修改畫布大小
相關
// 導入 ThreeJS
import * as three from 'three';
// 渲染器的建立
const renderer = new three.WebGLRenderer();
主邏輯
window.addEventListener('resize', () => {
renderer.setSize(window.innerWidth, window.innerHeight);
})
其中:
- renderer.setSize() 函數用于設定畫布的尺寸;該函數接收兩個參數,分别用于設定畫布的寬度及畫布的高度。
- window.innerWidth 與 window.innerHeight 分别對應浏覽器視口(浏覽器的可視區域)的目前寬度及高度。
執行效果
界面的自适應功能已被實作,但場景中的物體将随浏覽器視口尺寸的改變而被拉伸或擠壓。
分析:
渲染器以錄影機的各方面屬性(位置,角度等)來計算在畫布中需要繪制的内容(視錐體)。renderer.setSize() 僅改變了畫布大小,并沒有改變視錐體的寬高比,是以在我們更改畫布大小後場景中的元素将被拉伸。
視錐體
在三維計算機圖形學中,視錐體(英語:viewing frustum)又稱視景體、視錐,是三維世界中在螢幕上可見的區域,即虛拟錄影機的視野。
該區域的實際形狀依所模拟的錄影機鏡頭而定,但顧名思義,其常見的形狀是方平截頭體。将四棱錐截為平截頭體的兩個平面稱作近平面 和遠平面。如果某個物體到錄影機的距離比近平面近或比遠平面遠,那麼這個物體不會被顯示。
上述内容引用自 維基百科
修改視錐體的寬高比
你需要使用錄影機對象的 aspect 屬性指定視錐體的寬高比,并使用錄影機對象的 updateProjectionMatrix() 使寬高比生效。
相關
// 導入 ThreeJS
import * as three from 'three';
// 建立透視錄影機
const camera = new three.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
透視錄影機
在 ThreeJS 中,你可以使用如下代碼建立透視錄影機:
其中:
項目 | 描述 |
---|---|
fov | 視錐體垂直視野角度,預設值為 50。 |
aspect | 視錐體的寬高比,預設值為 1。 |
near | 規定視錐體近端面與錄影機之間的距離,預設值為 0.1。 |
far | 規定視錐體遠端面與錄影機之間的距離,預設值為 2000。 |
主邏輯
window.addEventListener('resize', () => {
renderer.setSize(window.innerWidth, window.innerHeight);
// 設定視錐體的寬高比
camera.aspect = window.innerWidth / window.innerHeight;
// 使得視錐體的寬高比生效
camera.updateProjectionMatrix();
})
執行效果
全屏顯示
在 Edge 浏覽器中,你可以通過敲擊 F11 來使得目前頁面進入或退出全屏顯示。當然你也可以通過 JavaScript 實作使用者可以通過其他方式來進入或退出全屏顯示。這裡我們将實作輕按兩下頁面進入或退出全屏顯示的效果。
dblclick 事件
當你在頁面中進行輕按兩下操作時将觸發 dbclick 事件,我們可以在該事件對應的事件處理函數中實作輕按兩下以進入或退出全屏顯示的功能。
// 為 window 對象添加監聽器以監聽 dblclick 事件
window.addEventListener('dblclick', () => {
// 在此處實作輕按兩下以進入或退出全屏顯示的功能
})
檢測全屏顯示狀态
在通過 JavaScript 代碼進入或退出全屏顯示前,我們需要檢測目前的全屏顯示狀态。你可以通過 document.fullscreenElement 來達成此目的。
document.fullscreenElement
document.fullscreenElement 傳回目前文檔中正在以全屏模式顯示的Element 節點,如果沒有使用全屏模式,則傳回 null 。
實作
window.addEventListener('dblclick', () => {
if(document.fullscreenElement){
// 若已有元素進入全屏顯示狀态,則執行
// 此部分代碼。
}else{
// 若無元素進入全屏顯示狀态将執行
// 此部分代碼。
}
})
注:
通過敲擊 F11 進入全屏顯示後,document.fullscreenElement 将傳回 null 。也就是說,document.fullscreenElement 不能檢測到通過敲擊 F11 進入全屏顯示後的狀态。
進入全屏顯示狀态
Element.requestFullscreen() 方法用于發出異步請求使元素進入全屏模式。
調用此 API 并不能保證元素一定能夠進入全屏模式。如果元素被允許進入全螢幕模式,傳回的 Promise 會 resolve,并且該元素會收到一個fullscreenchange 事件,通知它已經進入全屏模式。如果全屏請求被拒絕,傳回的 promise 會變成 rejected 并且該元素會收到一個fullscreenerror 事件。如果該元素已經從原來的文檔中分離,那麼該文檔将會收到這些事件。
相關
// ThreeJS 的導入
import * as three from 'three';
// 渲染器的建立
const renderer = new three.WebGLRenderer();
進入全屏顯示狀态
window.addEventListener('dblclick', () => {
if(document.fullscreenElement){
// 若已有元素進入全屏顯示狀态,則執行
// 此部分代碼。
}else{
renderer.domElement.requestFullscreen();
}
})
注:
- 你可以在進入或退出全屏顯示狀态前對 fullscreenchange 和 fullscreenerror 事件進行監聽,以便在某一進制素進入或退出全屏顯示狀态或進行前兩種可能(某一進制素進入或退出全屏顯示狀态)時發生錯誤時進行合适的處理,提高對程式的掌控能力。
- 系統将維護全屏顯示棧,若你在進入全屏顯示狀态後 N 次執行進入全屏顯示狀态的相關代碼,那麼你需要執行退出全屏顯示狀态的操作 N+1 次才能夠完全退出全屏顯示狀态。
退出全屏顯示狀态
你可以通過執行 document.exitFullScreen() 函數來退出目前所處的全屏顯示狀态。
window.addEventListener('dblclick', () => {
if(document.fullscreenElement){
document.exitFullscreen();
}else{
renderer.domElement.requestFullscreen();
}
})
尾聲
💕歡迎建議💕 如果你對這篇部落格右什麼意見,歡迎指出。
💞歡迎提問💞 如果各位對文章中的某些内容不太了解,歡迎提問。