簡述
前面的畫布具有個固定的尺寸,尺寸為800x600,雖然沒必要讓W(xué)ebGL適配整個屏幕,但是為了更好的體驗,適配屏幕大小是必須的。
首先,期望畫布占用所有可用空間。然后,我們需要確保如果用戶調(diào)整其窗口大小,它仍然適配。最后,我們需要為用戶提供一種以全屏方式體驗的方法。
設(shè)置
初始內(nèi)容(私信索取)包含之前完成的內(nèi)容。立方體位于中心,并且可以通過拖拽操作來移動相機。
適配視口
要使畫布適配視口,而非使用sizes變量中的固定數(shù)字,使用window.innerWidth和window.innerHeight
// ...
// 尺寸
const sizes = {
? ? width: window.innerWidth,
? ? height: window.innerHeight
}
// ...
此時可以看到畫布的大小等同于視口大小。但不幸的是,外圍有白色的邊框和一個滾動條。
這是因為瀏覽器有默認樣式,比如重要的標題、帶下劃線的鏈接、段落之間的空白以及頁面上的填充。有很多方法可以解決這個問題,這取決于網(wǎng)頁所使用的框架。如果頁面上有其他內(nèi)容,請在執(zhí)行操作時盡量不影響其他內(nèi)容。
這里使用CSS來解決這個問題。
在模版中,已經(jīng)在src/style.css文件中鏈接了一個CSS。如果不常使用Webpack,代碼看上去會很奇怪,但CSS文件確實是在script.js的第一行引入。
import './style.css'
CSS文件中可以直接寫CSS代碼,頁面會自動重載
首先要做的一件事就是使用通配符*移除margin和padding類型的元素
*
{
? ? margin: 0;
? ? padding: 0;
}
然后,使用class選擇webgl畫布,并調(diào)整畫布對齊左上角
.webgl
{
? ? position: fixed;
? ? top: 0;
? ? left: 0;
}
這樣就不用再指定畫布的寬和高,因為Three.js在調(diào)用renderer.setSize()方法時,完成了調(diào)整。
另一個問題,拖拽操作時畫布會有一個藍色的輪廓,這主要發(fā)生在Chrome上。要解決這個問題,只需要在.webgl上添加outline: none;
.webgl
{
? ? position: fixed;
? ? top: 0;
? ? left: 0;
? ? outline: none;
}
如果想刪除滾動條,可以在html和body上添加overflow: hidden
html,
body
{
? ? overflow: hidden;
}
但是這樣并不會在窗口大小發(fā)生變化時,重新調(diào)整畫布大小。
句柄調(diào)整大小
要想調(diào)整畫布大小,首先需要知道窗口何時調(diào)整大小,所以應(yīng)在窗口監(jiān)聽resize事件。
在sizes變量后添加resize監(jiān)聽器
window.addEventListener('resize', () =>
{
? ? console.log('window has been resized')
})
此時,在調(diào)整窗口大小時會觸發(fā)一個函數(shù),并顯示在控制臺。
可以通過這個更新值。
首先,更新變量sizes
window.addEventListener('resize', () =>
{
? ? //更新sizes
? ? sizes.width = window.innerWidth
? ? sizes.height = window.innerHeight
})
然后通過更新aspect屬性,修改相機寬高比
window.addEventListener('resize', () =>
{
? ? // ...
? ? // 更新相機
? ? camera.aspect = sizes.width / sizes.height
})
當修改相機屬性時,比如修改aspect時,也需要使用camera.updateProjectionMatrix()更新投影矩陣.
window.addEventListener('resize', () =>
{
? ? // ...
? ? camera.updateProjectionMatrix()
})
最后,需要更新renderer。更新renderer也會自動更新畫布的寬和高。
window.addEventListener('resize', () =>
{
? ? // ...
? ? // 更新 renderer
? ? renderer.setSize(sizes.width, sizes.height)
})
綜上
window.addEventListener('resize', () =>
{
? ? //更新sizes
? ? sizes.width = window.innerWidth
? ? sizes.height = window.innerHeight
? ? // 更新相機
? ? camera.aspect = sizes.width / sizes.height
? ? camera.updateProjectionMatrix()
? ? //更新renderer
? ? renderer.setSize(sizes.width, sizes.height)
})
此時可以根據(jù)需要調(diào)整窗口大小,且畫布完美覆蓋視口,不會有寬邊和滾動條。