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

2023-10-27

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()
        }
    }
})

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

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

  • dojo dijit.form.DateTextBox 约束不起作用,datetextbox

    嗨 我是 javascript 和 dojo 的新手 我正在尝试使用两个带有下拉日历的 dijit DateTextBox 来建立数据库查询的日期范围 一旦选择了开始日期或结束日期 我想限制可用的日期 以便不可能选择按时间顺序排列在开始日期
  • 关闭选项卡时要求确认[关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 当我在某些浏览器上关闭页面时 我希望出现一个消息框 并询问我是否真的要关闭页面 有两个按钮 如果我单击No那么这个标签就不会被关闭 我怎样
  • 为什么 JavaScript base-36 转换看起来不明确

    我目前正在编写一段使用 Base 36 编码的 JavaScript 我遇到了这个问题 parseInt welcomeback 36 toString 36 看来要回归了 welcomebacg 我在 Chrome 开发者控制台和 Nod
  • 如何重定向到 instagram://user?username={username}

    我的 html 页面上有这个链接 可以在特定用户上打开 Instagram 应用程序 a href Link to Instagram Profile a 我一直在寻找自动运行 url instagram user username USE
  • 我想检查 $('#td1').text() === "x" 是否?

    我想检查innerHtml是否有X或O 所以我不能再次添加任何其他东西 但它不起作用 添加检查代码后它就停止了 我在这里尝试做一个简单的XO游戏来更熟悉javascript和jquery 我也不确定是否可以用 jQuery 做到这一点
  • 检查 JavaScript 字符串是否为 URL

    JavaScript 有没有办法检查字符串是否是 URL 正则表达式被排除在外 因为 URL 很可能是这样写的stackoverflow 也就是说它可能没有 com www or http 如果你想检查一个字符串是否是有效的 HTTP UR
  • 使用 Angular 下载具有动态 src 的脚本

    Angular 提供了通过动态名称动态加载模板的方法ng include 该部分中的内联 JS 和 CSS 可以正常加载 但没有一个好的方法来下载带有动态 url 的脚本 我们需要下载脚本 相对于调用它们的 html 部分的路径 即我们有一
  • 如何抑制窗口鼠标滚轮滚动...?

    我正在开发嵌入页面中的画布应用程序 我有它 因此您可以使用鼠标滚轮放大绘图 但不幸的是 这会滚动页面 因为它是文章的一部分 当我在 dom 元素上滚动鼠标滚轮时 是否可以阻止鼠标滚轮在窗口上滚动 附加鼠标滚轮 不是 Gecko DOMMou
  • 标签获取 href 值

    我有以下 html div class threeimages a img alt Australia src Images Services 20button tcm7 9688 gif a div class text h2 a hre
  • Jquery/Javascript 上传和下载文件,无需后端

    是否可以在没有后端服务器的情况下在 JavaScript 函数中下载和上传文件 我需要导出和导入由 JavaScript 函数生成的 XML 我想创建按钮 保存 xml 来保存文件 但我不知道是否可行 另一方面 我希望将 XML 文件直接上
  • 使用 KnockoutJs 映射插件进行递归模板化

    我正在尝试使用以下方法在树上进行递归模板化ko映射 插入 http knockoutjs com documentation plugins mapping html 但我无法渲染它 除非我定义separate每个级别的模板 在以下情况下
  • 如何使输入字段和提交按钮变灰

    我想变灰这两件事 http doorsplit heroku com 歌曲输入字段和提交按钮 直到用户输入艺术家 有没有一种简单的方法可以通过 JQuery 来做到这一点 艺术家输入字段的id是 request artist 你可以这样做
  • Angular 2+ 安全性;保护服务器上的延迟加载模块

    我有一个 Angular 2 应用程序 用户可以在其中输入个人数据 该数据在应用程序的另一部分进行分析 该部分仅适用于具有特定权限的人员 问题是我们不想让未经授权的人知道how我们正在分析这些数据 因此 如果他们能够在应用程序中查看模板 那
  • 为 illustrator 导出脚本以保存为 web jpg

    任何人都可以帮我为 illustrator CC2017 编写一个脚本 将文件以 JPG 格式导出到网络 旧版 然后保存文件并关闭 我有 700 个文件 每个文件有 2 个画板 单击 文件 gt 导出 gt 另存为 Web 旧版 然后右键文
  • 在 vue.js 中访问数组对象属性

    给定以下数组vue js packageMaps Object packageMap 0 Object Id 16 PackageType flag list ProductCode F BannerBase packageMap 1 Ob
  • Safari 支持 JavaScript window.onerror 吗?

    我有一个附加到 window onerror 的函数 window onerror function errorMsg url line window alert asdf 这在 firefox chrome 和 IE 中工作正常 但在 s
  • 如何更改此 jquery 插件的时区/时间戳?

    我正在使用这个名为 timeago 的插件 在这里找到 timeago yarp com 它工作得很好 只是它在似乎不同的时区运行 我住在美国东部 费城时区 当我将准确的 EST 时间放入 timeago 插件时 比如 2011 05 28
  • JQuery 图像上传不适用于未来的活动

    我希望我的用户可以通过帖子上传图像 因此 每个回复表单都有一个上传表单 用户可以通过单击上传按钮上传图像 然后单击提交来提交帖子 现在我的上传表单可以上传第一个回复的图像 但第二个回复的上传不起作用 我的提交过程 Ajax 在 php 提交
  • 如何仅在最后一个
  • 处给出透明六边形角度?
  • 我必须制作这样的菜单 替代文本 http shup com Shup 330421 1104422739 My Desktop png http shup com Shup 330421 1104422739 My Desktop png
  • 如何在 pg-promise 中设置模式

    我正在搜索的文档pg 承诺 https github com vitaly t pg promise特别是在创建客户端时 但我无法找到设置连接中使用的默认架构的选项 它始终使用public架构 我该如何设置 通常 为数据库或角色设置默认架构

随机推荐