Three.js零基础入门教程

参考资料:Threejs中文网

1. threejs文件包下载和目录简介

在正式学习Three.js之前,先做一些必要的准备工作,具体说就是下载threejs官方文件包,threejs官方文件包提供了很多有用的学习资源

Three.js版本问题

Three.js处于飞速发展之中,过去几年和现在Three.js基本上每个月都会发布一个新的版本,主要是增加一些新的功能,也可能废弃或更名某些API。

threejs官方文件包所有版本:https://github.com/mrdoob/three.js/releases

Threejs中文网(电子书课件):www.webgl3d.cn

版本问题如何对待

three.js官网 (opens new window)可以下载three.js文件包,不过默认是最新版本的,three.js官网的文档一般也是当前最新版本。

因为threejs每月更新的时候,API会有变化,我的建议是,实际开发的时候,three.js API的使用规则,一切以你项目threejs版本对应的文档为准,下节课会具体给大家说怎么在本地预览任何你想要的版本文档。

Threejs官网中文文档链接:https://threejs.org/docs/index.html#manual/zh/

特定版本three.js文件包下载

github链接查看所有版本threejs:https://github.com/mrdoob/three.js/releases

选择你需要的版本three.js文件包下载,然后解压,就可以预览里面的很多学习资源。

如果你那边gihtub打不开或下载很慢,你可以去three.js中文网 (opens new window)提供网盘资源下载。

threejs文件资源目录介绍

下载three.js文件包解压后,你可以看到如下目录(不同版本会略有差异)。

对于开发者而言,大家经常接触的是文档docs案例examples两个文件夹,平时查看文档,可以打开文档docs里面html文件,案例examples里面提供了海量threejs功能案例。

three.js-文件包
└───build——three.js相关库,可以引入你的.html文件中。│
└───docs——Three.js API文档文件│───index.html——打开该文件,本地离线方式预览threejs文档
└───examples——大量的3D案例,是你平时开发参考学习的最佳资源│───jsm——threejs各种功能扩展库
└───src——Three.js引擎的源码,有兴趣可以阅读。│
└───editor——Three.js的可视化编辑器,可以编辑3D场景│───index.html——打开应用程序  

2. 学习环境-编辑器和静态服务器

工欲善其事,必先利其器,写threejs代码之前,需要先准备一个用于threejs学习的开发环境。

  1. vscode代码编辑器
  2. 本地静态服务器——预览文档、课程案例源码
本地静态服务器

平时学习Three.js,如果你想预览代码3D效果,咱们需要提供一个本地静态服务器的开发环境,如果你有一定的web前端基础,提到本地静态服务器肯定不陌生。

作为前端工程师,大家都知道,正式的web项目开发,往往会用webpack或vite或其它方式配置一个开发环境。

如果只是学习threejs的话,没必要这么麻烦,我最建议的方式就是,通过代码编辑器快速创建本地静态服务器,比如vsocde,安装live-server插件即可。

vscode配置live-server插件

不同代码编辑器创建本地静态服务器方式不同,课程就以vscocde为了大家演示。

  • 安装

vscode软件界面左侧,点击扩展,输入live-server关键词查询安装。

  • 使用

如果你想预览代码3D效果,打开对应.html文件,右键点击Open with Live Server即可。

预览3D案例和文档
  • 预览课程案例源码

打开课件案例,注意把Three.js视频教程源码文件作为根目录,使用vscode创建本地静态服务就可以预览。

  • 预览官方examples中案例
  • 本地预览文档

threejs整个官方文件包作为根目录,用本地静服务打开任何一个.html文件即可预览

three.js-文件包
...
└───docs——Three.js API文档文件│───index.html——打开该文件,本地离线方式预览threejs文档
└───examples——大量的3D案例,是你平时开发参考学习的最佳资源│───.html——各种3D案例
...    

3. 开发和学习环境,引入threejs

本节课主要给大家说下threejs怎么引入的问题。

  1. 开发环境:项目开发引入threejs,比如vue或react脚手架引入threejs。
  2. 学习环境:入门threejs阶段,.html文件中直接引入threejs
项目的开发环境引入threejs

比如你采用的是Vue + threejsReact + threejs技术栈,这很简单,threejs就是一个js库,直接通过npm命令行安装就行。

npm安装特定版本three.js(注意使用哪个版本,查文档就查对应版本)

// 比如安装148版本
npm install three@0.148.0 --save
npm安装后,如何引入three.js

执行import * as THREE from 'three';,ES6语法引入three.js核心。

// 引入three.js
import * as THREE from 'three';

如果你没有前端ES6基础,可以参考我分享的前端公开课ES6入门教程 (opens new window)。

npm安装后,如何引入three.js其他扩展库

除了three.js核心库以外,在threejs文件包中examples/jsm目录下,你还可以看到各种不同功能的扩展库。

一般来说,你项目用到那个扩展库,就引入那个,用不到就不需要引入。

// 引入扩展库OrbitControls.js
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
// 引入扩展库GLTFLoader.js
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
// 扩展库引入——旧版本,比如122, 新版本路径addons替换了examples/jsm
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';
学习环境:.html文件中直接引入threejs

如果不是正式开发Web3D项目,只是学习threejs功能,完全没必要用webpack或vite搭建一个开发环境。

学习使用的环境,只要创建一个.html文件,编写threejs代码,最后通过本地静态服务打开.html文件就行。

script标签方式引入three.js

你可以像平时开发web前端项目一样,通过script标签把three.js当做一个js库引入你的项目。

three.js库可以在threejs官方文件包下面的build目录获取到。

<script src="./build/three.js"></script>
//随便输入一个API,测试下是否已经正常引入three.js
console.log(THREE.Scene); 
ES6 import方式引入

给script标签设置type="module",也可以在.html文件中使用import方式引入three.js。

<script type="module">
// 现在浏览器支持ES6语法,自然包括import方式引入js文件
import * as THREE from './build/three.module.js';
</script>
type="importmap"配置路径

学习环境中,.html文件引入three.js,最好的方式就是参考threejs官方案例,通过配置<script type="importmap">,实现学习环境.html文件和vue或reaact脚手架开发环境一样的写法。这样你实际项目的开发环境复制课程源码,不用改变threejs引入代码。

下面配置的type="importmap"代码具体写法不用掌握记忆,复制粘贴后,能修改目录就行,你可以去电子书课件或者课件源码中复制。

<!-- 具体路径配置,你根据自己文件目录设置,我的是课件中源码形式 -->
<script type="importmap">{"imports": {"three": "../../../three.js/build/three.module.js"}}
</script>
<!-- 配置type="importmap",.html文件也能和项目开发环境一样方式引入threejs -->
<script type="module">import * as THREE from 'three';// 浏览器控制台测试,是否引入成功console.log(THREE.Scene);
</script>
type="importmap"配置——扩展库引入

通过配置<script type="importmap">,让学习环境.html文件,也能和vue或react开发环境中一样方式方式引入threejs扩展库。

配置addons/等价于examples/jsm/

<script type="importmap">{"imports": {"three": "./three.js/build/three.module.js","three/addons/": "./three.js/examples/jsm/"}}
</script>
<script type="module">// three/addons/路径之后对应的是three.js官方文件包`/examples/jsm/`中的js库// 扩展库OrbitControls.jsimport { OrbitControls } from 'three/addons/controls/OrbitControls.js';// 扩展库GLTFLoader.jsimport { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';console.log(OrbitControls);console.log(GLTFLoader);
</script>

4. 第一个3D案例—创建3D场景

入门Three.js的第一步,就是认识场景Scene相机Camera渲染器Renderer三个基本概念,接下来,咱们通过三小节课,大家演示“第一个3D案例”完成实现过程。

学习建议:只要你能把第一个3D案例搞明白,后面学习就会非常顺利了。

本节课先完成第一个3D案例的一部分,也就是3D场景Scene的创建。

三维场景Scene

你可以把三维场景Scene (opens new window)对象理解为虚拟的3D场景,用来表示模拟生活中的真实三维场景,或者说三维世界。

// 创建3D场景对象Scene
const scene = new THREE.Scene();
#物体形状:几何体Geometry

Three.js提供了各种各样的几何体API,用来表示三维物体的几何形状。

文档搜索关键词geometry你可以看到threejs提供各种几何体相关API,具体使用方法,也可以参考文档。

//创建一个长方体几何对象Geometry
const geometry = new THREE.BoxGeometry(100, 100, 100); 
物体外观:材质Material

如果你想定义物体的外观效果,比如颜色,就需要通过材质Material相关的API实现。

threejs不同材质渲染效果不同,下面就以threejs最简单的网格基础材质MeshBasicMaterial (opens new window)为例给大家实现一个红色材质效果。

//创建一个材质对象Material
const material = new THREE.MeshBasicMaterial({color: 0xff0000,//0xff0000设置材质颜色为红色
}); 
物体:网格模型Mesh

实际生活中有各种各样的物体,在threejs中可以通过网格模型Mesh (opens new window)表示一个虚拟的物体,比如一个箱子、一个鼠标。

// 两个参数分别为几何体geometry、材质material
const mesh = new THREE.Mesh(geometry, material); //网格模型对象Mesh
模型位置.position

实际生活中,一个物体往往是有位置的,对于threejs而言也是一样的,你可以通过位置属性.position定义网格模型Mesh在三维场景Scene中的位置。

const mesh = new THREE.Mesh(geometry, material); //网格模型对象Mesh
//设置网格模型在三维空间中的位置坐标,默认是坐标原点
mesh.position.set(0,10,0);
.add()方法

在threejs中你创建了一个表示物体的虚拟对象Mesh,需要通过.add()方法,把网格模型mesh添加到三维场景scene中。

scene.add(mesh); 
#后续内容

写到这里,我知道你已经迫不及待想执行代码看看渲染效果了,那么你需要看看后面两节课关于相机Camera渲染器Renderer的介绍

5. 第一个3D案例—透视投影相机

Threejs如果想把三维场景Scene渲染到web网页上,还需要定义一个虚拟相机Camera,就像你生活中想获得一张照片,需要一台用来拍照的相机。

透视投影相机PerspectiveCamera

Threejs提供了正投影相机OrthographicCamera (opens new window)和透视投影相机PerspectiveCamera (opens new window)。本节课先给大家比较常用的透视投影相机PerspectiveCamera

透视投影相机PerspectiveCamera本质上就是在模拟人眼观察这个世界的规律。

// 实例化一个透视投影相机对象
const camera = new THREE.PerspectiveCamera();
相机位置.posiiotn

生活中用相机拍照,你相机位置不同,拍照结果也不同,threejs中虚拟相机同样如此。

比如有一间房子,你拿着相机站在房间里面,看到的是房间内部,站在房子外面看到的是房子外面效果。

相机对象Camera具有位置属性.posiiotn,通过位置属性.posiiotn可以设置相机的位置。

//相机在Three.js三维坐标系中的位置
// 根据需要设置相机位置具体值
camera.position.set(200, 200, 200); 
相机观察目标.lookAt()

你用相机拍照你需要控制相机的拍照目标,具体说相机镜头对准哪个物体或说哪个坐标。对于threejs相机而言,就是设置.lookAt()方法的参数,指定一个3D坐标。

//相机观察目标指向Threejs 3D空间中某个位置
camera.lookAt(0, 0, 0); //坐标原点
camera.lookAt(0, 10, 0);  //y轴上位置10
camera.lookAt(mesh.position);//指向mesh对应的位置

判断相机相对三维场景中长方体位置

你可以把三维场景中长方体mesh想象为一个房间,然后根据相机位置和长方体位置尺寸对比,判断两者相对位置。你可以发现设置相机坐标(200, 200, 200),位于长方体外面一处位置。

// 长方体尺寸100, 100, 100
const geometry = new THREE.BoxGeometry( 100, 100, 100 );
const mesh = new THREE.Mesh(geometry,material);
// 相机位置xyz坐标:0,10,0
mesh.position.set(0,10,0);
// 相机位置xyz坐标:200, 200, 200
camera.position.set(200, 200, 200); 

定义相机渲染输出的画布尺寸

你生活中相机拍照的照片是有大小的,对于threejs而言一样,需要定义相机在网页上输出的Canvas画布(照片)尺寸,大小可以根据需要定义,这里先随机定义一个尺寸。

Canvas画布:课程中会把threejs虚拟相机渲染三维场景在浏览器网页上呈现的结果称为Canvas画布

// 定义相机输出画布的尺寸(单位:像素px)
const width = 800; //宽度
const height = 500; //高度
#透视投影相机PerspectiveCamera:视锥体

透视投影相机的四个参数fov, aspect, near, far构成一个四棱台3D空间,被称为视锥体,只有视锥体之内的物体,才会渲染出来,视锥体范围之外的物体不会显示在Canvas画布上。

视锥体

// width和height用来设置Three.js输出的Canvas画布尺寸(像素px)
const width = 800; //宽度
const height = 500; //高度
// 30:视场角度, width / height:Canvas画布宽高比, 1:近裁截面, 3000:远裁截面
const camera = new THREE.PerspectiveCamera(30, width / height, 1, 3000);

PerspectiveCamera参数介绍:

PerspectiveCamera( fov, aspect, near, far )
参数含义默认值
fov相机视锥体竖直方向视野角度50
aspect相机视锥体水平方向和竖直方向长度比,一般设置为Canvas画布宽高比width / height1
near相机视锥体近裁截面相对相机距离0.1
far相机视锥体远裁截面相对相机距离,far-near构成了视锥体高度方向2000

6. 第一个3D案例—渲染器

生活中如果有了景物相机,那么如果想获得一张照片,就需要你拿着相机,按一下,咔,完成拍照。对于threejs而言,如果完成“咔”这个拍照动作,就需要一个新的对象,也就是WebGL渲染器WebGLRenderer (opens new window)。

WebGL渲染器WebGLRenderer

通过WebGL渲染器WebGLRenderer (opens new window)可以实例化一个WebGL渲染器对象。

// 创建渲染器对象
const renderer = new THREE.WebGLRenderer();
设置Canvas画布尺寸.setSize()
// 定义threejs输出画布的尺寸(单位:像素px)
const width = 800; //宽度
const height = 500; //高度
renderer.setSize(width, height); //设置three.js渲染区域的尺寸(像素px)
渲染器渲染方法.render()

渲染器WebGLRenderer执行渲染方法.render()就可以生成一个Canvas画布(照片),并把三维场景Scene呈现在canvas画布上面,你可以把.render()理解为相机的拍照动作“咔”。

renderer.render(scene, camera); //执行渲染操作
渲染器Canvas画布属性.domElement

渲染器WebGLRenderer通过属性.domElement可以获得渲染方法.render()生成的Canvas画布,.domElement本质上就是一个HTML元素:Canvas画布。

document.body.appendChild(renderer.domElement);
Canvas画布插入到任意HTML元素中
<div id="webgl" style="margin-top: 200px;margin-left: 100px;"></div>
document.getElementById('webgl').appendChild(renderer.domElement);

7. 三维坐标系-加强三维空间认识

本节课的目的就是为了加强大家对threejs三维空间的认识。

辅助观察坐标系

THREE.AxesHelper()的参数表示坐标系坐标轴线段尺寸大小,你可以根据需要改变尺寸。

// AxesHelper:辅助观察的坐标系
const axesHelper = new THREE.AxesHelper(150);
scene.add(axesHelper);
材质半透明设置

设置材质半透明,这样可以看到坐标系的坐标原点。

const material = new THREE.MeshBasicMaterial({color: 0x0000ff, //设置材质颜色transparent:true,//开启透明opacity:0.5,//设置透明度
});
AxesHelper的xyz轴

three.js坐标轴颜色红R、绿G、蓝B分别对应坐标系的xyz轴,对于three.js的3D坐标系默认y轴朝上

设置模型在坐标系中的位置或尺寸

通过模型的位置、尺寸设置,加深3D坐标系的概念。

测试:设置长方体xyz不同方向尺寸

// 设置几何体长宽高,也就是x、y、z三个方向的尺寸
//对比三个参数分别对应xyz轴哪个方向
new THREE.BoxGeometry(100, 60, 20);

测试:改变位置

// 设置模型mesh的xyz坐标
mesh.position.set(100,0,0);
改变相机参数——预览新的渲染效果

你可以尝试源码中改变相机的参数,看看场景中的物体渲染效果怎么变化。

相机放在x轴负半轴,目标观察点是坐标原点,这样相当于相机的视线是沿着x轴正方向,只能看到长方体的一个矩形平面。

camera.position.set(-1000, 0, 0);
camera.lookAt(0, 0, 0);
// 相机视线沿着x轴负半轴,mesh位于相机后面,自然看不到
camera.position.set(-1000, 0, 0);
camera.lookAt(-2000, 0, 0);

相机far偏小,mesh位于far之外,物体不会显示在画布上。

// const camera = new THREE.PerspectiveCamera(30, width / height, 1, 3000);
// 你可以进行下面测试,改变相机参数,把mesh放在视锥体之外,看看是否显示
// 3000改为300,使mesh位于far之外,mesh不在视锥体内,被剪裁掉
const camera = new THREE.PerspectiveCamera(30, width / height, 1, 300);

视锥体

8. 光源对物体表面影响

实际生活中物体表面的明暗效果是会受到光照的影响,threejs中同样也要模拟光照Light对网格模型Mesh表面的影响。

你可以打开课件中案例源码,对比有光照和无光照两种情况,网格模型Mesh表面的差异。

受光照影响材质

threejs提供的网格材质,有的受光照影响,有的不受光照影响。

基础网格材质MeshBasicMaterial (opens new window)不会受到光照影响。

//MeshBasicMaterial不受光照影响
const material = new THREE.MeshBasicMaterial(); 

漫反射网格材质MeshLambertMaterial (opens new window)会受到光照影响,该材质也可以称为Lambert网格材质,音译为兰伯特网格材质。

一个立方体长方体使用MeshLambertMaterial材质,不同面和光线夹角不同,立方体不同面就会呈现出来不同的明暗效果。

//MeshLambertMaterial受光照影响
const material = new THREE.MeshLambertMaterial(); 
光源简介

Three.js提供了多种模拟生活中光源的API,文档搜索关键词light就可以看到。

点光源

点光源PointLight (opens new window)可以类比为一个发光点,就像生活中一个灯泡以灯泡为中心向四周发射光线。

//点光源:两个参数分别表示光源颜色和光照强度
// 参数1:0xffffff是纯白光,表示光源颜色
// 参数2:1.0,表示光照强度,可以根据需要调整
const pointLight = new THREE.PointLight(0xffffff, 1.0);
光源位置

你把点光源想象为一个电灯泡,你在3D空间中,放的位置不同,模型的渲染效果就不一样。

注意光源位置尺寸大小:如果你希望光源照在模型的外表面,那你就需要把光源放在模型的外面。

//点光源位置
pointLight.position.set(400, 0, 0);//点光源放在x轴上

改变光源位置,观察网格模型表面的明暗变化。

directionalLight.position.set(100, 60, 50); 
光源添加到场景

光源和网格模型Mesh对应一样是三维场景的一部分,自然需要添加到三维场景中才能起作用。

scene.add(directionalLight); //点光源添加到场景中

9. 相机控件OrbitControls

平时开发调试代码,或者展示模型的时候,可以通过相机控件OrbitControls实现旋转缩放预览效果。

OrbitControls使用

你可以打开课件案例源码测试下效果。

  • 旋转:拖动鼠标左键
  • 缩放:滚动鼠标中键
  • 平移:拖动鼠标右键
引入扩展库OrbitControls.js
// 引入轨道控制器扩展库OrbitControls.js
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';

注意:如果你在原生.html文件中,使用上面引入方式import { OrbitControls } from 'three/addons/controls/OrbitControls.js';,注意通过<script type="importmap">配置。

<script type="importmap">{"imports": {"three": "../../../three.js/build/three.module.js","three/addons/": "../../../three.js/examples/jsm/"}}
</script>
使用OrbitControls
// 设置相机控件轨道控制器OrbitControls
const controls = new OrbitControls(camera, renderer.domElement);
// 如果OrbitControls改变了相机参数,重新调用渲染器渲染三维场景
controls.addEventListener('change', function () {renderer.render(scene, camera); //执行渲染操作
});//监听鼠标、键盘事件
OrbitControls本质

OrbitControls本质上就是改变相机的参数,比如相机的位置属性,改变相机位置也可以改变相机拍照场景中模型的角度,实现模型的360度旋转预览效果,改变透视投影相机距离模型的距离,就可以改变相机能看到的视野范围。

controls.addEventListener('change', function () {// 浏览器控制台查看相机位置变化console.log('camera.position',camera.position);
});

10. 平行光与环境光

本节课通过平行光DirectionalLight (opens new window)和环境光AmbientLight (opens new window)进一步了解光照对应模型Mesh表面的影响。

点光源辅助观察PointLightHelper

通过点光源辅助观察对象PointLightHelper (opens new window)可视化点光源。

预览观察:可以借助相机控件OrbitControls旋转缩放三维场景便于预览点光源位置

// 光源辅助观察
const pointLightHelper = new THREE.PointLightHelper(pointLight, 10);
scene.add(pointLightHelper);

改变点光源位置,观察光照效果变化。

directionalLight.position.set(100, 60, 50);
// 改变点光源位置,使用OrbitControls辅助观察
pointLight.position.set(-400, -200, -300);
环境光设置

环境光AmbientLight (opens new window)没有特定方向,只是整体改变场景的光照明暗。

//环境光:没有特定方向,整体改变场景的光照明暗
const ambient = new THREE.AmbientLight(0xffffff, 0.4);
scene.add(ambient);
平行光

平行光DirectionalLight (opens new window)就是沿着特定方向发射。

// 平行光
const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
// 设置光源的方向:通过光源position属性和目标指向对象的position属性计算
directionalLight.position.set(80, 100, 50);
// 方向光指向对象网格模型mesh,可以不设置,默认的位置是0,0,0
directionalLight.target = mesh;
scene.add(directionalLight);
平行光辅助观察DirectionalLightHelper

通过点光源辅助观察对象DirectionalLightHelper (opens new window)可视化点光源。

// DirectionalLightHelper:可视化平行光
const dirLightHelper = new THREE.DirectionalLightHelper(directionalLight, 5,0xff0000);
scene.add(dirLightHelper);
平行光与Mesh表面光线反射规律

平行光照射到网格模型Mesh表面,光线和模型表面构成一个入射角度,入射角度不同,对光照的反射能力不同。

光线照射到漫反射网格材质MeshLambertMaterial (opens new window)对应Mesh表面,Mesh表面对光线反射程度与入射角大小有关。

// 对比不同入射角,mesh表面对光照的反射效果
directionalLight.position.set(100, 0, 0);
directionalLight.position.set(0, 100, 0);
directionalLight.position.set(100, 100, 100);
directionalLight.position.set(100, 60, 50);
//directionalLight.target默认指向坐标原点

11. 动画渲染循环

threejs可以借助HTML5的API请求动画帧window.requestAnimationFrame实现动画渲染。

请求动画帧window.requestAnimationFrame
// requestAnimationFrame实现周期性循环执行
// requestAnimationFrame默认每秒钟执行60次,但不一定能做到,要看代码的性能
let i = 0;
function render() {i+=1;console.log('执行次数'+i);requestAnimationFrame(render);//请求再次执行函数render
}
render();
threejs旋转动画

动画说白了就是一张张照片,连起来依次展示,这样就形成一个动画效果,只要帧率高,人的眼睛就感觉不到卡顿,是连续的视频效果。

const renderer = new THREE.WebGLRenderer();
renderer.setSize(width, height);
// renderer.render(scene, camera); //执行渲染操作
document.body.appendChild(renderer.domElement);// 渲染函数
function render() {renderer.render(scene, camera); //执行渲染操作mesh.rotateY(0.01);//每次绕y轴旋转0.01弧度requestAnimationFrame(render);//请求再次执行渲染函数render,渲染下一帧
}
render();
计算两帧渲染时间间隔和帧率
// 渲染循环
const clock = new THREE.Clock();
function render() {const spt = clock.getDelta()*1000;//毫秒console.log('两帧渲染时间间隔(毫秒)',spt);console.log('帧率FPS',1000/spt);renderer.render(scene, camera); //执行渲染操作mesh.rotateY(0.01);//每次绕y轴旋转0.01弧度requestAnimationFrame(render);//请求再次执行渲染函数render,渲染下一帧
}
render();
渲染循环和相机控件OrbitControls

设置了渲染循环,相机控件OrbitControls就不用再通过事件change执行renderer.render(scene, camera);,毕竟渲染循环一直在执行renderer.render(scene, camera);

12. Canvas画布布局和全屏

threejs渲染输出的结果就是一个Cavnas画布,canvas画布也是HTML的元素之一,这意味着three.js渲染结果的布局和普通web前端习惯是一样的。

通过renderer.domElement属性可以访问threejs的渲染结果,也就是HTML的元素canvas画布。

非全屏局部布局

你可以把threejs的渲染结果renderer.domElement,插入到web页面上任何一个元素中,只要符合你项目的布局规则即可。

<div id="webgl" style="margin-top: 100px;margin-left: 200px;"></div>
<script type="module">
// width和height用来设置Three.js输出的Canvas画布尺寸(像素px)
const width = 800; //宽度
const height = 500; //高度const camera = new THREE.PerspectiveCamera(30, width / height, 1, 3000);/*** 创建渲染器对象*/
const renderer = new THREE.WebGLRenderer();
renderer.setSize(width, height); //设置three.js渲染区域的尺寸(像素px)
renderer.render(scene, camera); //执行渲染操作
//three.js执行渲染命令会输出一个canvas画布,也就是一个HTML元素,你可以插入到web页面中
// document.body.appendChild(renderer.domElement);
document.getElementById('wegbl').appendChild(renderer.domElement);

#全屏渲染
// width和height用来设置Three.js输出的Canvas画布尺寸(像素px)
const width = window.innerWidth; //窗口文档显示区的宽度作为画布宽度
const height = window.innerHeight; //窗口文档显示区的高度作为画布高度
const renderer = new THREE.WebGLRenderer();
document.body.appendChild(renderer.domElement);

全屏布局注意CSS的设置。

<style>body{overflow: hidden;margin: 0px;}
</style>
canvas画布宽高度动态变化

canvas画布宽高度动态变化,需要更新相机和渲染的参数,否则无法正常渲染。

// onresize 事件会在窗口被调整大小时发生
window.onresize = function () {// 重置渲染器输出画布canvas尺寸renderer.setSize(window.innerWidth, window.innerHeight);// 全屏情况下:设置观察范围长宽比aspect为窗口宽高比camera.aspect = window.innerWidth / window.innerHeight;// 渲染器执行render方法的时候会读取相机对象的投影矩阵属性projectionMatrix// 但是不会每渲染一帧,就通过相机的属性计算投影矩阵(节约计算资源)// 如果相机的一些属性发生了变化,需要执行updateProjectionMatrix ()方法更新相机的投影矩阵camera.updateProjectionMatrix();
};

附送250套精选项目源码

源码截图

 源码获取:关注公众号「码农园区」,回复 【源码】,即可获取全套源码下载链接

 

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

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

相关文章

《数学学习与研究》投稿难度大吗?

《数学学习与研究》杂志的投稿难度相对适中。 一方面&#xff0c;它作为一本有一定影响力的数学专业期刊&#xff0c;对稿件的质量有一定要求。论文需要具备一定的创新性、科学性和逻辑性&#xff0c;研究内容要具有一定的价值和深度。 另一方面&#xff0c;与一些核心期刊相…

TEE的存储系统是如何实现的?如何保证其安全的?

在一般情况下&#xff0c;TEE OS 中是没有磁盘的&#xff0c;也没有 EMMC/UFS 驱动&#xff0c;因此无法在 TEE OS 侧完成数据落盘。 那么&#xff0c;TEE OS 的安全存储是如何实现的呢&#xff1f;事实上&#xff0c;TEE OS 侧的安全存储是通过反向存储在 REE 侧来实现的。有…

web安全基础学习笔记

这里写目录标题 1.使用hackbar2.php漏洞基本分析 弱类型语言2.2 php漏洞找到隐藏的源代码之 index.php~2.3 php漏洞找到隐藏的源代码之 vim的临时文件 /.index.php.swp3.php漏洞基本分析 数组 3.php漏洞基本分析 extract4.php漏洞基本分析 strpos eregi函数漏洞4.php漏洞基本分…

携手星展银行,YonSuite财资管理助力企业“扬帆出海”

在全球经济一体化的浪潮下&#xff0c;越来越多的中国企业怀揣着“扬帆出海”的雄心壮志&#xff0c;积极开拓国际市场。然而&#xff0c;在海外市场面临的复杂环境和激烈竞争中&#xff0c;如何高效管理财务资金、优化资源配置、降低运营风险&#xff0c;成为摆在众多出海企业…

Qt图像处理技术十二:QImage实现边缘检测(sobel算法)

效果图 原理 Sobel算法是一种常用的边缘检测算法&#xff0c;它利用图像的灰度变化来检测图像中物体的边缘。Sobel算法主要包括以下几个步骤&#xff1a; 灰度化&#xff1a; 首先将彩色图像转换为灰度图像&#xff0c;因为灰度图像只包含单通道的灰度信息&#xff0c;有利于…

通过fiftyone按分类下载open-images-v7数据集,并转成yolov5可直接训练的格式

import osimport fiftyone as fo import fiftyone.zoo as foz import yamlclasses [Person, # 人 - 0Car, # 轿车 - 1Taxi, # 出租车 - 2Ambulance, # 救护车 - 3Bus, # 公共汽车 - 4Bicycle, # 自行车 - 5Motorcycle, # 摩托车 - 6Dog, # 狗 - 7Cat, # 猫 - 8M…

000002 - Hadoop环境安装

Hadoop及其大数据生态圈 1. 背景2. 实践2.1 Linux服务器准备2.2 在其中一台服务器上安装JDK2.3 在其中一台服务器上安装HADOOP2.4 本地模式运行一个hadoop案例 3. 自动化部署 1. 背景 要搭建Hadoop集群环境&#xff0c;我们需要执行如下 准备三台Linux服务器&#xff0c;服务…

Python实现日志的记录

1 日志 1、介绍 日志&#xff08;Log&#xff09;是一个记录事件或系统活动的文件或数据集&#xff0c;日志是系统管理员和开发者用于诊断问题、监视系统性能、以及追踪用户活动的关键工具。包含以下&#xff1a; 系统日志&#xff1a;记录操作系统、应用程序、硬件组件等的事…

lcd屏幕verilog显示

一,VGA原理和时序 计算机显示区的显示有许多标准,常见的有VGA、SVGA等。在这里我们用VGA接口来控制显示器,也就是视频图形阵列。作为一 种标准的显示接口得到广泛的应用。 常见的彩色显示器一般由 CRT(阴极射线管)构成,色彩是由R、G、B(红、黄、 蓝)三基色组成。显示是…

前端UI框架Element Plus 和 Ant Design Vue哪个好

Element Plus 和 Ant Design Vue 都是基于 Vue.js 的 UI 组件库&#xff0c;它们具备一系列可复用的组件和丰富的功能&#xff0c;并且是当前国内主流的两个 UI 组件库。 &#xff08;1&#xff09;Element Plus 是饿了么前端团队推出的开源项目&#xff0c;是对 Element UI 的…

completefuture造成的rpc重试事故

前言 最近经历了一个由于 completefuture 的使用&#xff0c;导致RPC重试机制触发而引起的重复写入异常的生产bug。复盘下来&#xff0c;并非是错误的使用了completefuture&#xff0c;而是一些开发时很难意识到的坑。 背景 用户反馈通过应用A使用ota批量升级设备时存在概率…

文字游侠AI:一键创作头条爆文!(附渠道和保姆级教程)

在互联网的迅猛发展中&#xff0c;自媒体已然成为一条崭新的职业路径&#xff0c;吸引着越来越多的人通过各类平台分享观点与知识&#xff0c;同时获取相应的收益。今日头条便是一个极为出色的自媒体平台&#xff0c;旗下的图文项目更是一条实现收益的有效途径。 对于众多非专业…

【SpringBoot + Vue 尚庭公寓实战】租期管理接口实现(四)

【SpringBoot Vue 尚庭公寓实战】租期管理接口实现&#xff08;四&#xff09; 文章目录 【SpringBoot Vue 尚庭公寓实战】租期管理接口实现&#xff08;四&#xff09;1、查询全部租期列表2、保存或更新租期信息3、根据ID删除租期 租期管理共有三个接口&#xff0c;分别是 保…

IP纯净度对跨境电商有影响吗?

当我们谈论代理IP时&#xff0c;通常会提到一个重要概念&#xff0c;那就是“IP纯净度”。 IP纯净度是指代理IP服务中所提供的IP地址的质量、干净程度和安全性&#xff0c;纯净度高的IP地址通常具备低恶意软件攻击的风险、良好的访问效果、稳定性和速度以及隐私保护等特点。在…

动态内存管理(malloc,calloc,realloc,free)+经典笔试题

动态内存管理 一. malloc 和 free1. malloc2. free 二. calloc三. realloc四.动态内存的错误1.对NULL指针的解引用操作2.对动态开辟空间的越界访问3.对非动态开辟内存使用free释放4.使用free释放一块动态开辟内存的一部分5.对同一块动态内存多次释放6.动态开辟内存忘记释放&…

python连接Mongodb数据库,报错:pymongo.errors.ServerSelectionTimeoutError

python连接mongdb数据库&#xff0c;本来是可以的&#xff0c;但是研发更换新的数据库后&#xff0c;一直报错&#xff1a;pymongo.errors.ServerSelectionTimeoutError&#xff0c;但是在其他人电脑上脚本执行成功。 详见报错截图&#xff1a; 在网上找了很久的解决方案&…

图标绘制软件draw.io中文安装包

Draw.io&#xff08;也称为Diagrams&#xff09;是一款功能强大的免费在线图表绘制工具。它支持绘制多种类型的图表&#xff0c;如流程图、UML图、组织结构图等&#xff0c;满足了从商务到工程设计的多领域需求。软件界面直观友好&#xff0c;操作简单&#xff0c;用户无需安装…

【网络基础1】

文章目录 学习目标一、网络基础11.网络的重要性2.osi7层模式3.协议和osi7层模型的关系4.数据的封装和解封装5.tcp的三次握手6.Ddos攻击讲解7.Tcp的四次挥手 二、网络基础21.文字编码2.IP地址的划分3.子网掩码4.同网段ip才能直接通信5.DNS解析6.DNS解析命令7.短域名为什么值钱8.…

docker命令 docker ps -l (latest)命令在 Docker 中用于列出最近一次创建的容器

文章目录 12345 1 docker ps -l 命令在 Docker 中用于列出最近一次创建的容器。具体来说&#xff1a; docker ps&#xff1a;这个命令用于列出当前正在运行的容器。-l 或 --latest&#xff1a;这个选项告诉 docker ps 命令只显示最近一次创建的容器&#xff0c;不论该容器当前…

Python代码限定抽奖次数的方法

在许多应用场景中&#xff0c;抽奖活动需要限定参与次数以确保公平性和控制成本。本文将介绍如何使用Python代码实现抽奖次数的限定。我们将讨论基本的实现方法&#xff0c;并展示一个完整的代码示例。 基本思路 限定抽奖次数的基本思路是使用一个计数器来记录每个用户已经参…