ThreeJS 之界面控制

news2024/9/23 13:23:51

文章目录

  • 参考
  • 描述
  • 界面自适应
      • 问题
      • resize 事件
      • 修改画布大小
      • 修改视锥体的宽高比
  • 全屏显示
      • dblclick 事件
      • 检测全屏显示状态
      • 进入全屏显示状态
      • 退出全屏显示状态
  • 尾声

参考

项目描述
ThreeJS官方文档
哔哩哔哩老陈打码
搜索引擎Bing
MDN 文档document.mozFullScreenElement
MDN 文档Element.requestFullscreen()
MDN 文档Document.exitFullscreen()

描述

项目描述
npm8.19.3
nodev16.19.0
Edge110.0.1587.41 (正式版本) (64 位)
ThreeJS0.148.0
webpack5.75.0
webpack-cli5.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);
})

其中:

  1. renderer.setSize() 函数用于设置画布的尺寸;该函数接收两个参数,分别用于设置画布的宽度及画布的高度。
  2. window.innerWidthwindow.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 中,你可以使用如下代码创建透视摄像机:

PerspectiveCamera( fov : Number, aspect : Number, near : Number, far : Number );

其中:

项目描述
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 并不能保证元素一定能够进入全屏模式。如果元素被允许进入全屏幕模式,返回的 Promiseresolve,并且该元素会收到一个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();
    }
})

注:

  1. 你可以在进入或退出全屏显示状态前对 fullscreenchangefullscreenerror 事件进行监听,以便在某一元素进入或退出全屏显示状态或进行前两种可能(某一元素进入或退出全屏显示状态)时发生错误时进行合适的处理,提高对程序的掌控能力。

  2. 系统将维护全屏显示栈,若你在进入全屏显示状态后 N 次执行进入全屏显示状态的相关代码,那么你需要执行退出全屏显示状态的操作 N+1 次才能够完全退出全屏显示状态。

退出全屏显示状态

你可以通过执行 document.exitFullScreen() 函数来退出当前所处的全屏显示状态。

window.addEventListener('dblclick', () => {
    if(document.fullscreenElement){
        document.exitFullscreen();
    }else{
        renderer.domElement.requestFullscreen();
    }
})

尾声

💕欢迎建议💕 如果你对这篇博客右什么意见,欢迎指出。

💞欢迎提问💞 如果各位对文章中的某些内容不太理解,欢迎提问。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/357040.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

LeetCode题目笔记——6359. 替换一个数字后的最大差值

文章目录题目描述题目链接题目难度——简单方法一:替换代码/Python代码优化总结题目描述 给你一个整数 num 。你知道 Danny Mittal 会偷偷将 0 到 9 中的一个数字 替换 成另一个数字。 请你返回将 num 中 恰好一个 数字进行替换后,得到的最大值和最小值…

CTK学习:(一)编译CTK

CTK插件框架简介 CTK Plugin Framework是用于C++的动态组件系统,以OSGi规范为模型。在此框架下,应用程序由不同的组件组成,遵循面向服务的方法。 ctk是一个开源项目,Github 地址:https://github.com/commontk。 源码地址commontk/CTK: A set of common support code for…

信小程序点击按钮绘制定制转发分享图

1. 说明 先上代码片断分享链接: https://developers.weixin.qq.com/s/vl3ws9mA72GG 使用 painter 画图 按钮传递定制化信息 效果如下: 2. 关键代码说明 文件列表如下: {"usingComponents": {"painter": "/com…

基于springboot的停车场管理系统(程序+文档)

大家好✌!我是CZ淡陌。将再这里为大家分享优质的实战项目,本人在Java毕业设计领域有多年的经验,陆续会更新更多优质的Java实战项目,希望你能有所收获,少走一些弯路。 🍅更多优质项目👇&#x1f…

Android实例仿真之二

目录 三 从无入手 第一阶段 第二阶段 第三阶段 第四阶段 第五阶段 第六阶段 第七阶段 八 举两个典型例子: 九 逆向工程 三 从无入手 这节标题叫从无入手,什么意思呢?如果没有Android这个实例存在,你要做一个类似Android…

Mysql数据库事务

数据库事务 数据库事务由一组sql语句组成。 所有sql语句执行成功则事务整体成功;任一条sql语句失败则事务整体失败,数据恢复到事务之前的状态。 Mysql 事务操作 开始事务 start transaction;- 或 begin;事务开始后,对数据的增删改操作不…

MySQL最佳实践

一、MySQL查询执行过程 1.MySQL分层结构 MySQL8.0没有查询缓存的功能了,如果频繁修改缓存,将会损耗性能查询流程就按照分层结构就可以清楚,只要了解各个组件的各自功能就行分析器主要分析语法和词法是否正确优化器主要优化SQL语句 二、MySQL更新执行过程 更新主要涉及两个重…

SpringCloud - Ribbon负载均衡

目录 负载均衡流程 负载均衡策略 Ribbon加载策略 负载均衡流程 Ribbon将http://userservice/user/1请求拦截下来,帮忙找到真实地址http://localhost:8081LoadBalancerInterceptor类对RestTemplate的请求进行拦截,然后从Eureka根据服务id获取服务列表&…

正点原子ARM裸机开发篇

裸机就是手动的操作硬件来实现驱动设备,后面会有驱动框架不需要这么麻烦 第八章 汇编 LED 灯实验 核心过程 通过汇编语言来控制硬件(驱动程序) 代码流程 1、使能 GPIO1 时钟 GPIO1 的时钟由 CCM_CCGR1 的 bit27 和 bit26 这两个位控制&…

SSL/STL是什么?怎么工作的?Keystore 和 Truststore是什么?

安全套接字层(Secure Sockets Layer),也称为 SSL,是一种加密协议(encryption protocol),可在 Internet 上的设备之间创建身份验证的通道(authenticated channel),以便可以安全地共享信息。本质上&#xff0…

动态规划专题精讲1

致前行的人: 要努力,但不要着急,繁花锦簇,硕果累累都需要过程! 前言: 本篇文章为大家带来一种重要的算法题,就是动态规划类型相关的题目,动态规划类的题目在笔试和面试中是考察非常高…

【日常点滴019】Python制作流浪气球游戏(导弹射击类)

Python制作流浪气球游戏(导弹射击类)教学课程代码(分步教学版)1、构建全局通用代码结构2、构建气球精灵类3、构建导弹精灵类4、碰撞检测5、构建游戏信息类 (最终完整代码)教学课程代码(分步教学…

基于springboot+vue的食疗系统

基于springbootvue的食疗系统 ✌全网粉丝20W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 🍅文末获取项目下载方式🍅 一、项目背景介绍&…

java面试题-并发基础

1.多线程的出现是要解决什么问题的? 本质什么?提高程序性能:单线程程序只能按照固定的顺序依次执行每个任务,无法同时处理多个任务。多线程技术可以在同一时间内执行多个任务,从而提高程序的运行效率和响应速度。提高程序的并发性&#xff…

前端借助Canvas实现压缩图片两种方法

一、具体代码 1、利用canvas压缩图片方法一 // 第一种压缩图片方法(图片base64,图片类型,压缩比例,回调函数)// 图片类型是指 image/png、image/jpeg、image/webp(仅Chrome支持)// 该方法对以上三种图片类型都适用 压缩结果的图片base64与原类型相同// …

Python自动化测试-使用Pandas来高效处理测试数据

Python自动化测试-使用Pandas来高效处理测试数据 目录:导读 一、思考 二、使用pandas来操作Excel文件 三、使用pandas来操作csv文件 四、总结 一、思考 1.Pandas是什么? 功能极其强大的数据分析库可以高效地操作各种数据集 csv格式的文件Excel文件H…

Python3-基本数据类型

Python3 基本数据类型 Python 中的变量不需要声明。每个变量在使用前都必须赋值,变量赋值以后该变量才会被创建。 在 Python 中,变量就是变量,它没有类型,我们所说的"类型"是变量所指的内存中对象的类型。 等号&…

注意力机制笔记——结合沐神和B站老弓up主

B站【大白话浅谈【注意力机制】】 聚类 是针对 样本, 注意力机制是针对样本相关性,来进行计算的 自注意力机制 指的是 query ,key,value都是同一个部分。 可以学到 类似的 短语 ,和 语义特征。如its 指代的对象。 评论区大佬 根据这篇论文《Effective Approaches to…

[ vulhub漏洞复现篇 ] Drupal 远程代码执行漏洞(CVE-2018-7602)

🍬 博主介绍 👨‍🎓 博主介绍:大家好,我是 _PowerShell ,很高兴认识大家~ ✨主攻领域:【渗透领域】【数据通信】 【通讯安全】 【web安全】【面试分析】 🎉点赞➕评论➕收藏 养成习…

设计模式之各种设计模式总结与对比

目录1 目标2 定位3 一句话归纳设计原则4 G0F 23种设计模式简介5 设计模式使用频次总结6 —句话归纳设计模式7 设计模式之间的关联关系和对比1 目标 1、 简要分析GoF 23种设计模式和设计原则,做整体认知。 2、 剖析Spirng的编程思想,启发思维,为之后深入学习Spring…