three.js初使用

一、Three.js介绍

Three.js是一个基于WebGL的JavaScript库,它使得在网页上创建和显示3D图形变得简单。Three.js提供了一套易于使用的API,封装了WebGL的复杂性,让开发者能够快速地创建3D内容,而无需深入了解WebGL的细节。简而言之就是一个网页端轻量化渲染3d的库,我们可以用它结合VUE\REACT来做一些数字孪生的前端项目。

二、关于Three.js的一些资料

使用前请下载并配置完Node.js
官方文件包:https://github.com/mrdoob/three.js/releases
中文教程网:http://www.webgl3d.cn/

三、具体使用

首先我们要了解three.js的结构,其中包括场景、相机、渲染器、几何体、材质、网格、光源等(以vue3为例)。
在使用之前我们要引入three库
在终端输入

1
npm i three

script标签内导入

1
import * as THREE from "three"

1.场景

场景可以理解为存放所有3d对象的容器,粗略的理解为与div一样,只是前者存放3d对象,后者存放dom元素。
创建场景(示例)

1
scene = new THREE.Scene()

2.相机

相机可以理解为人眼的视角,我们所看到场景内的3d对象都是那一面的照片,我们通过移动相机可以观察到3d对象每一面的照片,也就有了3d感
创建相机

1
2
3
4
5
6
7
8
camera = new THREE.PerspectiveCamera(
75, // 视场角(FOV),单位是角度,值越大,视角越广
container.value.clientWidth / container.value.clientHeight, // 宽高比
0.1, // 近裁剪面,也就是看到最近的点位
1000 // 远裁剪面,最远的点位
)
// 设置相机位置(有x,y,z决定,初始原点,下述代码沿z轴后移5个单位),同理可改变x,y轴方向
camera.position.z = 5

不知道如何判断相机位置可以借助世界坐标辅助器,可以在页面看到辅助坐标轴

1
2
3
4
//添加世界坐标辅助器
axesHelper=new THREE.AxesHelper(5)
//添加至场景
scene.add(axesHelper)

3.渲染器

渲染器将相机“拍”到的画面渲染到页面
渲染器代码示例

1
2
3
4
5
6
// 创建WebGL渲染器(使用抗锯齿优化)
renderer = new THREE.WebGLRenderer({ antialias: true })
// 设置渲染器尺寸为容器大小
renderer.setSize(container.value.clientWidth, container.value.clientHeight)
// 将渲染器的canvas元素添加到DOM容器,前端能够展示
document.body.appendChild(renderer.domElement);//这里插入了body中,实际上可以自定义选择插入容器

4.几何体、材质、网格

几何体也就是3d对象,材质则是3d对象视觉上的质感、网格则是将几何体与材质结合在一起
接下来我们创建一个绿色的正方体,并将其添加入场景

1
2
3
4
5
6
7
8
9
10
  // 创建立方体几何体(长宽高各为1单位)
const geometry = new THREE.BoxGeometry(1, 1, 1)
// 创建基础材质(绿色)
// ! MeshBasicMaterial 不受光材质
// ! MeshLambertMaterial 漫反射 受光材质
const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 })
// 创建网格对象(组合几何体和材质)
cube = new THREE.Mesh(geometry, material)
// 将立方体添加到场景
scene.add(cube)

5.光源

设置光源体现出立体感,

1
2
3
const directionalLight = new THREE.DirectionalLight(0xffffff, 4);//0xffffff设置光源颜色,5设置了光源强度
directionalLight.position.set(30, 10, 20); // 设置光源的方向,即从(30,10,20)坐标射向原点
scene.add(directionalLight);

6.其他

可以设置函数令其旋转

1
2
3
4
5
6
7
8
9
10
11
function animate() {
// 请求下一帧动画(保持60FPS循环)
animationId = requestAnimationFrame(animate)

// 更新立方体旋转角度(x轴和y轴各加0.01弧度)
cube.rotation.x += 0.01
cube.rotation.y += 0.01

// 渲染场景(将3D场景绘制到2D画布)
renderer.render(scene, camera)
}

除以上外,还有其他api可以调用

1
2
3
4
5
6
7
8
9
10
11
12
13
  //添加控制器
controls = new OrbitControls(camera, renderer.domElement);
//设置阻尼,带惯性
controls.enableDamping=true
//设置阻尼系数
controls.dampingFactor=0.05
//设置自动旋转
controls.autoRotate=true
//设置速度
// 设置相机位置(沿z轴后移5个单位)
camera.position.z = 5
camera.position.x=0.5
camera.position.y=0.5

四、代码示例

vue3代码

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
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
<script setup>
// 导入Vue相关API
import { onMounted, onUnmounted, ref } from 'vue'
//导入轨道控制器
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls"
// 导入Three.js库
import * as THREE from 'three'

// 使用ref创建容器引用,用于挂载Three.js渲染器
const container = ref(null)
// 声明Three.js相关变量
let scene, camera, renderer, cube, animationId, axesHelper, controls
const textureLoader = new THREE.TextureLoader();
textureLoader.setCrossOrigin('anonymous');
// 组件挂载生命周期钩子
onMounted(() => {
initThree() // 初始化Three.js场景
setupResizeHandler() // 设置窗口resize监听
animate() // 启动动画循环
})

// 组件卸载生命周期钩子
onUnmounted(() => {
cancelAnimationFrame(animationId) // 停止动画循环
window.removeEventListener('resize', handleResize) // 移除resize监听
scene = null // 释放场景内存(Three.js对象需要手动销毁)
})

// 初始化Three.js核心要素
function initThree() {

// 创建场景(所有3D对象的容器)
scene = new THREE.Scene()

// 创建透视相机(模拟人眼视角)
camera = new THREE.PerspectiveCamera(
75, // 视场角(FOV),单位是角度
container.value.clientWidth / container.value.clientHeight, // 宽高比
0.1, // 近裁剪面
1000 // 远裁剪面
)


// 创建WebGL渲染器(使用抗锯齿优化)
renderer = new THREE.WebGLRenderer({ antialias: true })
// 设置渲染器尺寸为容器大小
renderer.setSize(container.value.clientWidth, container.value.clientHeight)
// 将渲染器的canvas元素添加到DOM容器
container.value.appendChild(renderer.domElement)

// 创建立方体几何体(长宽高各为1单位)
const geometry = new THREE.BoxGeometry(1, 1, 1)
// 创建基础材质(绿色)
const material = new THREE.MeshLambertMaterial({ color: 0x00ff00 })
// 创建网格对象(组合几何体和材质)
cube = new THREE.Mesh(geometry, material)
// 将立方体添加到场景
scene.add(cube)
//创建平行光源
const directionalLight = new THREE.DirectionalLight(0xffffff, 4);//0xffffff设置光源颜色,5设置了光源强度
directionalLight.position.set(30, 10, 20); // 设置光源的方向,即从(30,10,20)坐标射向原点
scene.add(directionalLight);

//添加世界坐标辅助器
axesHelper = new THREE.AxesHelper(5)
scene.add(axesHelper)
//添加控制器
controls = new OrbitControls(camera, renderer.domElement);
//设置阻尼,带惯性
controls.enableDamping = true
//设置阻尼系数
controls.dampingFactor = 0.05
//设置自动旋转
// controls.autoRotate=true
//设置速度
// 设置相机位置(沿z轴后移5个单位)
camera.position.z = 5
camera.position.x = 0.5
camera.position.y = 0.5
}

// 动画循环函数
function animate() {
controls.update()
// 请求下一帧动画(保持60FPS循环)
animationId = requestAnimationFrame(animate)

// 更新立方体旋转角度(x轴和y轴各加0.01弧度)
// cube.rotation.x += 0.01
// cube.rotation.y += 0.01

// 渲染场景(将3D场景绘制到2D画布)
renderer.render(scene, camera)
}

// 窗口大小变化处理函数
function handleResize() {
// 更新相机宽高比
camera.aspect = container.value.clientWidth / container.value.clientHeight
// 更新相机投影矩阵(必须调用以应用新的宽高比)
camera.updateProjectionMatrix()
// 更新渲染器尺寸
renderer.setSize(container.value.clientWidth, container.value.clientHeight)
}

// 设置窗口resize事件监听
function setupResizeHandler() {
window.addEventListener('resize', handleResize)
}
</script>

<template>
<!-- Three.js容器元素,通过ref绑定到container变量 -->
<div ref="container" class="three-container"></div>
</template>

<style scoped>
/* 容器样式设置 */
.three-container {
width: 100vw;
/* 视窗宽度100% */
height: 100vh;
/* 视窗高度100% */
position: fixed;
/* 固定定位 */
top: 0;
/* 顶部对齐 */
left: 0;
/* 左侧对齐 */
/* 隐藏溢出内容,确保canvas不会超出视口 */
overflow: hidden;
}
</style>

three.js初使用
http://example.com/2025/04/02/thr初使用/
作者
印星
发布于
2025年4月2日
许可协议