- Threejs简介
- (是什么)Threejs是一个web端的3D图形引擎,能利用js创建和控制各种三维模型和场景
- (能用来做什么)可以用js开发各种复杂的三维场景、空间模型动画展示、各种三维小游戏(比如微信跳一跳就是Threejs开发)。
- (优势) 传统三维开发一般是c++ openGl,开发成本大效率低,threejs封装了大量底层图形计算,在js应用层能以很高的效率完成各种三维产品开发。
- (劣势) 学习曲线比较陡峭,需要掌握一定图形和数学知识,大模型3D场景对设备性能有一定的要求,小型场景问题不大。
基础坐标系概念
- 不同于常规前端开发只有xy两个坐标系,threejs多了一个z坐标轴,因此开发场景从二维的平面转换为了三维的立体空间,z轴是往屏幕外面朝向
- Threejs坐标系采用的是右手坐标系
Threejs安装
- npm模式安装:npm install three
// 方式 1: 导入整个 three.js核心库
import * as THREE from 'three';
const scene = new THREE.Scene();
// 方式 2: 仅导入你所需要的部分
import { Scene } from 'three';
const scene = new Scene();
- cdn模式安装,由于 three.js 依赖于ES module,因此任何引用它的script标签必须使用type="module"。如下所示:
<script type="importmap">
{
"imports": {
"three": "https://unpkg.com/three@<version>/build/three.module.js"
}
}
</script>
<script type="module">
import * as THREE from 'three';
const scene = new THREE.Scene();
</script>
基础结构搭建
- html 中 引入canvas组件
<canvas class="webgl"></canvas>
<style>
.webgl {
position: fixed;
top: 0;
left: 0;
outline: none;
}
</style>
渲染器 WebGLRenderer
- 渲染器是用来将Threejs的各种三维元素,通过canvas展示出来的一种渲染引擎。
- 设置好渲染器各种参数后,通过调用render方法来进行界面渲染
//先定义渲染器尺寸,下面是浏览器全屏
const size = {
width: window.innerWidth,
height: window.innerHeight,
}
//获取canvas Dom元素
const canvas = document.querySelector('canvas.webgl')
//将dom引入传入渲染器,用来创建渲染器
const renderer = new THREE.WebGLRenderer({ canvas })
//设置渲染器尺寸
renderer.setSize(size.width, size.height)
//设置渲染器像素比 避免有些高分辨率的设备把屏幕弄得太模糊,设置像素比最大2X
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2))
场景 Scene
- 场景就是整个三维空间所有虚拟元素容器,有点类似于前端的虚拟Dom
- 主要常用的方法是 add(),用来给场景添加各种元素
- 真正让场景生效的是渲染器的render方法会传入场景参数
//创建场景
const scene = new THREE.Scene()
网格对象 Mesh
- Mesh是一种三维网格对象,也就是放在三维空间种的实物,Mesh由2种东西合成:
-
- Geometry 几何体,用来定义是三维物体的形状大小和网格分段密度,比如BoxGeometry是长方体,可以传入长宽高参数。
- Material 附着在几何体上的材质,用来定义颜色、透明度等等
- 可以通过 mesh.position.set(0,0,0) 用来调整网格对象中心点的坐标
- 最后把网格对象加入场景中 scene.add(mesh)
//创建mesh模型(由几何体+材质) 正方体
//长宽高为1的立方体 长宽高的线条分段是5条,用来调整网格密度
const geometry = new THREE.BoxGeometry(1, 1, 1, 5, 5, 5)
const material = new THREE.MeshBasicMaterial({
color: 0x03c03c, // 材质的颜色
transparent:true,// 开启透明
opacity:0.5,// 设置透明度
wireframe: true, //显示网格虚线
})
const mesh = new THREE.Mesh(geometry, material)
mesh.position.set(0,0,0)
scene.add(mesh)
相机 Camera
- 横看成岭侧成峰,不同于二维平面,在三维世界中从不角度看同一样东西,会有完全不同的呈现,所以在Threejs中引入Camera的概念,也就是不同的观察视角
- PerspectiveCamera(fov, aspect, near, far) 相机有四个参数
-
- fov 视线观察角度 比如45就是以45度角来观察
- aspect 渲染器的宽高比
- near 从多近的距离才开始渲染,就是相机能看到的最近的距离
- far 最多渲染多远的距离,就是相机能看到的最远的距离
如图所示
//初始化相机 透视相机
//这里是以45度观察 不设最远最近距离
const camera = new THREE.PerspectiveCamera(45, size.width/size.height)
//相机的位置放在在 x=3 y=3 z=3的位置
camera.position.set(3, 3, 3)
//然后相机看向 x=0 y=0 z=0的位置
camera.lookAt(0, 0, 0)
//场景添加相机
scene.add(camera)
渲染
已经完成所有场景布置了, 可以调用渲染器的render渲染方法,需要传入参数场景Scene和相机camera
renderer.render(scene, camera)
这个时候就可以看到一个网格立方体了
辅助观察坐标系
但是这种太模糊,没有位置概念,可以引入辅助坐标系,以方便更好观察
💡 Tips:以下代码需要在render渲染调用之前加,render执行过后渲染就完毕了
//添加坐标轴 辅助查看
const axesHelper = new THREE.AxesHelper(150)
scene.add(axesHelper)
可以看到多了三个线,其中红色的是x轴、绿色是 y轴、蓝色的是z轴,xyz交汇处就是0,0,0原点
动态渲染
目前我们上面看到的渲染是静态渲染,只渲染了一次,可以利用requestAnimationFrame浏览器自带的刷新器,动态的去改变网格对象的参数,达到视线动态渲染旋转的效果
在最后面加上如下代码
// 动态渲染
const tick = () => {
renderer.render(scene, camera)
mesh && (mesh.rotation.x += 0.02) //以x轴旋转
// mesh && (mesh.rotation.y += 0.02) //以y轴旋转
// mesh && (mesh.rotation.z += 0.02) //以z轴旋转
window.requestAnimationFrame(tick)
}
tick()
就能看到立方体开始旋转了
调整观察视角
目前相机观察视角是固定的,利用OrbitControls可以利用鼠标或者手势拖拽调整相机的观察视角
//在代码最前面import 轨道控制器
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
//在渲染前创建轨道控制器 用来用鼠标控制相机
const controls = new OrbitControls(camera, renderer.domElement)
controls.enableDamping = true
// 动态渲染 更新控制器update
const tick = () => {
renderer.render(scene, camera)
mesh && (mesh.rotation.x += 0.02) //以x轴旋转
// mesh && (mesh.rotation.y += 0.02) //以y轴旋转
// mesh && (mesh.rotation.z += 0.02) //以z轴旋转
controls.update() // 更新控制器
window.requestAnimationFrame(tick)
}
tick()
附 gitte源码: ThreeJsDemo: ThreeJs Demo