【Three.js】第八章 Fullscreen and resizing 全屏和调整大小

08.Fullscreen and resizing 全屏和调整大小

介绍

我们的画布目前有一个固定的分辨率800x600。项目中不一定需要 WebGL 填满整个屏幕,但如果您想要身临其境的体验,填满整屏的体验可能会更好。
首先,我们想让画布占据所有屏幕可用空间。然后,我们需要确保在用户调整窗口大小时它仍然自适应变化视口。最后,我们需要为用户提供一种全屏体验的方法。

设置

入门包含我们在上一课中完成的内容。我们的立方体位于中心,我们可以拖放以移动相机。

适合视口

要使画布完全根据视口变化,那就不能在sizes变量中使用固定数字了,请使用window.innerWidthand window.innerHeight

// ...

// Sizes
const sizes = {
    
    
    width: window.innerWidth,
    height: window.innerHeight
}

// ...


您可以看到画布现在具有视口的宽度和高度。不幸的是,有一个白色边距和一个滚动条(如果看不到任何滚动条,请尝试滚动)。
原因是浏览器都有默认样式,例如重要的标题<h1>、带下划线的链接<a/>、段落之间的空格以及页面上的填充。有很多方法可以解决这个问题,这可能取决于您网站的其余页面。如果您有其他页面的内容,请尽量不要在执行此操作时污染全局样式。
我们将保持样式并使用 CSS 固定画布的位置。
我们的 HTML 加载src/style.css文件:

<link rel="stylesheet" href="./style.css">

您可以像往常一样编写标准 CSS,页面将自动重新加载。
首先要做的一件好事是使用*通配符删除所有元素上的marginpadding的样式:

*
{
    
    
    margin: 0;
    padding: 0;
}

然后,我们可以将画布固定在左上角,使用它的class webgl 来选择它:

.webgl
{
    
    
    position: fixed;
    top: 0;
    left: 0;
}

您不需要在画布上指定width 或者height因为 Three.js 在您调用renderer.setSize(...)该方法时已经处理好了。
拖放时,您可能已经注意到上面有一个蓝色轮廓。这主要发生在最新版本的 Chrome 上。要解决这个问题,我们可以简单地在.webgl添加outline: none

.webgl
{
    
    
    position: fixed;
    top: 0;
    left: 0;
    outline: none;
}

如果你想删除任何类型的滚动,即使是在触摸屏上,你可以在html,body上添加overflow: hidden

html,
body
{
    
    
    overflow: hidden;
}


不幸的是,如果调整窗口大小,画布将不会随之改变。
我们需要处理渲染器,让他自适应窗口调整大小

处理调整大小

要调整画布大小,我们首先需要知道何时调整窗口大小。为此,可以在窗口上监听resize事件。
添加侦听器resize,在浏览器的sizes变量改变之后会自动触发:

window.addEventListener('resize', () =>
{
    
    
    console.log('window has been resized')
})

现在我们在调整窗口大小时触发了一个函数,我们需要更新代码中的一些东西。
首先,我们必须更新sizes变量:

window.addEventListener('resize', () =>
{
    
    
    // Update sizes
    sizes.width = window.innerWidth
    sizes.height = window.innerHeight
})

其次,我们必须camera通过更改其aspect属性来更新纵横比:

window.addEventListener('resize', () =>
{
    
    
    // ...

    // Update camera
    camera.aspect = sizes.width / sizes.height
})

当您更改相机属性时,aspect还需要使用camera.updateProjectionMatrix()更新投影矩阵。稍后我们将讨论矩阵:

window.addEventListener('resize', () =>
{
    
    
    // ...

    camera.updateProjectionMatrix()
})

最后,我们必须更新renderer. 更新渲染器会自动更新画布的宽度和高度

window.addEventListener('resize', () =>
{
    
    
    // ...

    // Update renderer
    renderer.setSize(sizes.width, sizes.height)
})

全部代码:

window.addEventListener('resize', () =>
{
    
    
    // Update sizes
    sizes.width = window.innerWidth
    sizes.height = window.innerHeight

    // Update camera
    camera.aspect = sizes.width / sizes.height
    camera.updateProjectionMatrix()

    // Update renderer
    renderer.setSize(sizes.width, sizes.height)
})

您可以根据需要调整窗口大小,画布应覆盖视口而没有任何滚动条或溢出。

处理像素比

我们开发中,有些人可能会看到一种模糊的渲染和边缘形状像楼梯的伪影(称为锯齿),但不是所有人都会看到。如果遇到了这样的问题,那是因为您的屏幕像素比大于1
像素比对应于软件部分的一个像素单元在屏幕上有多少个物理像素。

一些历史

几年前,所有屏幕的像素比都1,一切都很好。但是当你仔细观察你的屏幕时,你可以看到那些像素,这限制了图像的精确度和字体的细度。
在这方面做得最多的公司是苹果公司。Apple 看到了机会,开始制造像素比为2Retina 的屏幕。现在,很多建设者都在这样做,你可以看到像素比更高的屏幕。
虽然这对图像质量来说是件好事,但像素比2意味着要渲染的像素也要多 4 倍。像素比3意味着要渲染的像素多 9 倍。
你猜怎么着?最高像素比通常出现在屏幕最小的设备上——移动设备。
包括帧速率。

处理像素比

window.devicePixelRatio获得您可以使用的屏幕像素比,获得像素比后只需调用renderer.setPixelRatio(...)更新渲染器的像素比。
您可能只想简单地将设备像素比发送到该方法,但最终会在高像素比设备上遇到性能问题。
像素比大于2主要是出于营销。你的眼睛几乎看不到23之间的区别,但它会产生性能问题并更快地耗尽电池。可以做的优化是将像素比限制为2. 为此,您可以使用Math.min()

renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2))


当像素比率发生变化时,有一些技术可以通知我们开发者,但它只涉及拥有多个像素比率不同的屏幕的用户,并且他们通常会在从一个屏幕切换到另一个屏幕时调整窗口大小。这就是为什么我们也只需将此方法添加到resize回调中:

window.addEventListener('resize', () =>
{
    
    
    // Update sizes
    sizes.width = window.innerWidth
    sizes.height = window.innerHeight

    // Update camera
    camera.aspect = sizes.width / sizes.height

    // Update renderer
    renderer.setSize(sizes.width, sizes.height)
    renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2))
})

处理全屏

现在我们的画布以正确的像素比例占据了所有可用空间,是时候添加对全屏的支持了。
首先,我们需要决定什么动作会触发全屏模式。它可以是一个 HTML 按钮,但我们案例将使用双击触发全屏。
当双击发生时,我们将切换全屏——这意味着如果窗口不是全屏,双击将启用全屏模式,如果窗口已经全屏,双击将退出全屏模式。
首先,我们需要监听双击事件,我们可以通过dblclick事件来实现:

window.addEventListener('dblclick', () =>
{
    
    
    console.log('double click')
})

此事件适用于除 Chrome Android 之外的大多数现代浏览器: https: //developer.mozilla.org/docs/Web/API/Element/dblclick_event
现在我们有了我们的双击事件,我们需要三样东西:

  • 一种知道它是否已经全屏的方法
  • 进入全屏模式的方法
  • 一种退出全屏模式的方法

要知道我们是否已经处于全屏模式,我们可以使用document.fullscreenElement

window.addEventListener('dblclick', () =>
{
    
    
    if(!document.fullscreenElement)
    {
    
    
        console.log('go fullscreen')
    }
    else
    {
    
    
        console.log('leave fullscreen')
    }
})

请求全屏的方法与元素相关联。这是因为您可以选择全屏显示的内容。它可以是整个页面、任何 DOM 元素或<canvas>.
我们将使用<canvas>并调用requestFullscreen()它的方法:

window.addEventListener('dblclick', () =>
{
    
    
    if(!document.fullscreenElement)
    {
    
    
        canvas.requestFullscreen()
    }
    else
    {
    
    
        console.log('leave fullscreen')
    }
})

退出全屏模式的方法可直接在document:

window.addEventListener('dblclick', () =>
{
    
    
    if(!document.fullscreenElement)
    {
    
    
        canvas.requestFullscreen()
    }
    else
    {
    
    
        document.exitFullscreen()
    }
})

您可以通过双击任意位置来切换全屏模式来测试结果。不幸的是,这不适用于 Safari
Safari浏览器正在花时间支持全屏等正式的简单功能,我们需要使用前缀版本使其适用于document.fullscreenElementcanvas.requestFullscreendocument.exitFullscreen

window.addEventListener('dblclick', () =>
{
    
    
    const fullscreenElement = document.fullscreenElement || document.webkitFullscreenElement

    if(!fullscreenElement)
    {
    
    
        if(canvas.requestFullscreen)
        {
    
    
            canvas.requestFullscreen()
        }
        else if(canvas.webkitRequestFullscreen)
        {
    
    
            canvas.webkitRequestFullscreen()
        }
    }
    else
    {
    
    
        if(document.exitFullscreen)
        {
    
    
            document.exitFullscreen()
        }
        else if(document.webkitExitFullscreen)
        {
    
    
            document.webkitExitFullscreen()
        }
    }
})

一切功能都应该在所有现代浏览器上正常工作,兼容所有浏览器。

猜你喜欢

转载自blog.csdn.net/m0_68324632/article/details/130790467