three.js官网:https://threejs.org/
three.js中文官网https://threejs.org/docs/index.html#manual/zh/
Three.js是用JavaScript编写的一个第三方库,用于实现很多的3D功能,它是基于WebGL进行封装的。而WebGL又是由OpenGL ES2.0+Javascript进行封装的,而OpenGLES 2.0又是OpenGL 三维图形 API 的一个子集,而OpenGL是用于渲染2D、3D矢量图形的跨语言、跨平台的应用程序编程接口(API)。
一句话定义:
Three.js就是给浏览器装上「三维显卡」的黑科技!它让JavaScript具备了在网页里创造《头号玩家》级别虚拟世界的能力。
技术栈套娃指南:
为什么选择Three.js?
为什么要安装?首先three本身是一个库,官方提供了调试
、预览
、案例
、编辑器
等
众所周知国内经常访问不到github,网速差也是通病,那么下载一个本地服务就很有必要了
GitHub仓库地址:https://github.com/mrdoob/three.js/releases
本地启动即可
比如你采用的是Vue + threejs或React + threejs技术栈,这很简单,threejs就是一个js库,直接通过npm命令行安装就行。
// 比如安装172版本 更新了这么多年还是0.都不算一个大版本
npm install three@0.172.0 --save
执行import * as THREE from 'three'
,ES6语法引入three.js核心 (都开始学three了默认会es6哦)。
// 引入three.js
import * as THREE from 'three';
Scene
你可以把三维场景Scene (opens new window)对象理解为虚拟的3D场景,用来表示模拟生活中的真实三维场景,或者说三维世界。
// 创建3D场景对象Scene
const scene = new THREE.Scene();
Geometry
Three.js提供了各种各样的几何体API,用来表示三维物体的几何形状。
//创建一个长方体几何对象Geometry
const geometry = new THREE.BoxGeometry(1, 1, 1)
Material
如果你想定义物体的外观效果,比如颜色,就需要通过材质Material
相关的API实现。
threejs不同材质渲染效果不同,下面就以threejs最简单的网格基础材质MeshBasicMaterial (opens new window)
// 创建材质
const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 })
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);
PerspectiveCamera
Threejs提供了正投影相机OrthographicCamera (opens new window)和透视投影相机PerspectiveCamera (opens new window)常用的透视投影相机PerspectiveCamera
。
透视投影相机PerspectiveCamera
本质上就是在模拟人眼观察这个世界的规律。
// 实例化一个透视投影相机对象
const camera = new THREE.PerspectiveCamera(
45, //视角
window.innerWidth / window.innerHeight, //宽高比
0.1, //近平面
1000 //远平面
)
.lookAt()
你用相机拍照你需要控制相机的拍照目标,具体说相机镜头对准哪个物体或说哪个坐标。对于threejs相机而言,就是设置.lookAt()
方法的参数,指定一个3D坐标。
// 设置相机位置
camera.position.z = 5
camera.lookAt(0, 0, 0) //原点
WebGLRenderer
// 创建渲染器对象
const renderer = new THREE.WebGLRenderer();
// 设置Canvas画布尺寸`.setSize()`
renderer.setSize(window.innerWidth, window.innerHeight)
.domElement
渲染器WebGLRenderer
通过属性.domElement
可以获得渲染方法.render()
生成的Canvas画布,.domElement
本质上就是一个HTML元素:Canvas画布。
document.body.appendChild(renderer.domElement);
.render()
renderer.render(scene, camera); //执行渲染操作
.add()
方法在threejs中你创建了一个表示物体的虚拟对象Mesh,需要通过.add()
方法,把网格模型mesh
添加到三维场景scene
中。
scene.add(mesh);
// 超能力三件套:场景+相机+渲染器(比灭霸手套少3个宝石)
const 舞台 = new THREE.Scene(); // 空荡荡的元宇宙地块
const 导演镜头 = new THREE.PerspectiveCamera(45, window.innerWidth/window.innerHeight, 0.1, 1000); // 第4个参数叫"视奸距离"
const 魔法画布 = new THREE.WebGLRenderer(); // 比达芬奇还牛的动态画布
// 创世代码:绿魔方的诞生(颜色值16进制是程序员的浪漫)
const 魔方 = new THREE.Mesh(
new THREE.BoxGeometry(1,1,1), // 谁说方块不能当主角?
new THREE.MeshBasicMaterial({ color: 0x00FF00 }) // 要想生活过得去...
);
魔方.position.set(0,0,0); // 中心点坐标,学不会的建议背诵全文
// 导演说Action!
导演镜头.position.z = 5; // 悄悄后撤步
魔法画布.setSize(window.innerWidth, window.innerHeight); // 全屏警告
document.body.appendChild(魔法画布.domElement); // 给浏览器来点小小的三维震撼
// 旋转吧!小方块!(帧动画比德芙还丝滑)
function 宇宙大爆炸() {
requestAnimationFrame(宇宙大爆炸);
魔方.rotation.x += 0.01; // 转太快会晕3D的亲
魔方.rotation.y += 0.01;
魔法画布.render(舞台, 导演镜头);
}
宇宙大爆炸();
// 导入threejs
import * as THREE from 'three'
// 创建场景
const scene = new THREE.Scene()
// 创建相机
const camera = new THREE.PerspectiveCamera(
45, //视角
window.innerWidth / window.innerHeight, //宽高比
0.1, //近平面
1000 //远平面
)
// 创建渲染器
const renderer = new THREE.WebGLRenderer()
renderer.setSize(window.innerWidth, window.innerHeight)
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
camera.lookAt(0, 0, 0) //原点
// 渲染函数
;(function animate() {
requestAnimationFrame(animate)
// 旋转
cube.rotation.x += 0.01
cube.rotation.y += 0.01
renderer.render(scene, camera)
})()