three.js快速入门-上

three.js快速入门-上

three.js介绍

image-20241014154310792

three.js三要素

基础三要素:

  1. 场景:放置物体的容器

  2. 摄像机:想象成人的眼睛,可以提调整位置,角度

    image-20241014154512777
  3. 渲染器:接收场景和摄像机,计算在浏览器上渲染的最终的2D画面

image-20241014154533431

简单案例-创建一个立方体

image-20241014160013115
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import * as THREE from 'three';

//创建场景
const scene = new THREE.Scene();
//创建相机
//参数1:视野角度
//参数2:长宽比
//参数3、4:近截面和远截面
const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );
//渲染器
const renderer = new THREE.WebGLRenderer();
//设置渲染器的大小,大小最好与canvas的大小一致
renderer.setSize( window.innerWidth, window.innerHeight );
//将渲染器的dom元素添加到html中
document.body.appendChild( renderer.domElement );
//创建几何体,该对象包括定点、面信息
const geometry = new THREE.BoxGeometry( 1, 1, 1 );
//给几何体设置材质,如颜色
const material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
//创建网格体,包含几何体及材质
const cube = new THREE.Mesh( geometry, material );
//将网格体添加到场景中
scene.add( cube );
//设置相机的位置
camera.position.z = 5;
//渲染出图形
renderer.render( scene, camera );
image-20241014155755056

案例摄像机参数

image-20241014160039673

增加一个坐标轴

一定要在renderer.render方法之前增加显示对象

1
2
3
const axesHelper = new THREE.AxesHelper( 50 );
scene.add( axesHelper );
renderer.render( scene, camera );
image-20241014160235180

轨道控制器

现在图形是渲染出来了,但是我想用鼠标进行放大缩小,以及旋转还是不行,这时就要使用到了轨道控制器。

轨道控制器的主要作用是使摄像机围绕目标进行轨道运动

使用方法:

  1. 单独引入OrbitControls轨道控制器构造函数
  2. 创建轨道控制器
  3. 在渲染循环中更新场景渲染
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
import * as THREE from 'three';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'

//controls.update()必须在相机位置变换后调用
//创建场景
const scene = new THREE.Scene();
//创建相机
//参数1:视野角度
//参数2:长宽比
//参数3、4:近截面和远截面
const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );
//渲染器
const renderer = new THREE.WebGLRenderer();
//设置渲染器的大小,大小最好与canvas的大小一致
renderer.setSize( window.innerWidth, window.innerHeight );
//将渲染器的dom元素添加到html中
document.body.appendChild( renderer.domElement );
//创建几何体,该对象包括定点、面信息
const geometry = new THREE.BoxGeometry( 1, 1, 1 );
//给几何体设置材质,如颜色
const material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
//创建网格体,包含几何体及材质
const cube = new THREE.Mesh( geometry, material );
//将网格体添加到场景中
scene.add( cube );
//设置相机的位置
camera.position.z = 5;
//渲染出图形

const axesHelper = new THREE.AxesHelper( 50 );
scene.add( axesHelper );


//创建控制器,参数1:控制的相机,参数2:鼠标交互的标签,也就是监听的canvas,画布鼠标交互
const controls = new OrbitControls( camera, renderer.domElement );


function animate() {
//根据浏览器自动刷新,也就是自动调用animate方法,不断递归调用此渲染函数
requestAnimationFrame( animate );

// 轨道控制器属性改变,需要更新轨道控制器才有效果
controls.update();
renderer.render( scene, camera );
}
//首次调用
animate()

场景自动适配大小

目前场景是在初始化时就已经固定了,如何浏览器窗口大小变化,场景式不跟随变化的,为了解决这个问题,需要进行场景自动适配大小

1
2
3
4
5
6
7
8
9
10
11
function resize(){
window.addEventListener('resize',()=>{
//设置画布的宽高
renderer.setSize( window.innerWidth, window.innerHeight );
//设置相机的宽高比,保证物体的长宽比不发生变化
camera.aspect = window.innerWidth/window.innerHeight;
//让摄像机重新计算每个像素点的位置和大小
camera.updateProjectionMatrix();
})
}
resize()

物体的移动和变换

  1. 可以直接移动几何对象geometry.translate(5,0,0)

  2. 可以对网格对象进行坐标的重新设置cube.position.x = 10

  3. 旋转:cube.rotation.x = Math.PI/4

  4. 缩放:cube.scale.z =2

旋转和缩放都是按照自己的坐标系,而不是按照世界坐标系,移动是按照世界坐标系

性能监视器

我们常用的监视器有三个

image-20241014162416190

使用方法

  1. 单独引入Stats附加组件
  2. 创建性能监视器
  3. 设置面板类型(0,1,2)
  4. 添加到DOM
1
2
3
4
import Stats from 'three/examples/jsm/libs/stats.module.js';
const sta = new Stats();
sta.showPanel(0)
document.body.appendChild(sta.domElement)

注意:为了让监视器实时显示,需要实时调用sta.update();

删除物体

three.js是不会自动删除物体的,为了他提高性能,避免内存泄漏,需要手动进行删除。

几何体

几何体常用来表示定义为属性集合的顶点信息,three.js在内部为每一个属性创建一个WebGLBuffer类型的对象。 这些实体仅有在调用BufferGeometry.dispose()的时候才会被删除。

材质

材质定义了物体将如何被渲染。 着色器程序只有在相应材质被废置后(Material.dispose())才能被删除。

注意:将一个mesh(网格)从场景中移除,是不会删除它的geometry(几何体)和material(材质)

1
2
3
4
//删除物体需要删除几何图形、材质对象、物体本身
cube.geometry.dispose();
cube.material.dispose();
scene.remove(cube);

光线投射

光线投射经常被用来与3D物体的鼠标交互

也就是相机的位置到鼠标点击的位置形成一条射线,该射线会穿过物体,这是就可以对穿过的物体进行操作了

image-20241014163457974

在得到场景中的鼠标的坐标点时,这里面涉及到了坐标的归一话问题,也就是canvas屏幕坐标系需要映射到WebGL坐标系

image-20241014163554767

转换公式

image-20241014163627306

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
function Select(){
//创建射线和二维点
const raycaster = new THREE.Raycaster();
const pointer = new THREE.Vector2();

window.addEventListener( 'click', (event) =>{
// 将鼠标位置归一化为设备坐标。x 和 y 方向的取值范围是 (-1 to +1)
pointer.x = ( event.clientX / window.innerWidth ) * 2 - 1;
pointer.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
//设置射线的两个点
raycaster.setFromCamera(pointer,camera);
//计算物体和射线的焦点,返回一个数组,由近到远
const intersects = raycaster.intersectObjects( scene.children );
if(intersects[0])
{
scene.remove(intersects[0].object)

console.log(intersects[0])
}

});
}

three.js中文手册

作者

步步为营

发布于

2024-10-14

更新于

2025-03-15

许可协议