three.js 零基础到入门
-
- 什么是 three.js
- 为什么使用 three.js
- 使用 Three.js
-
- 1. 创建场景
-
- 示例
- 2.创建相机
- 3. 创建立方体并添加网格地面
-
- 示例
- 5. 创建渲染器
-
- 示例
- 6. 添加效果(移动/雾/相机跟随物体/背景)
-
- 自动旋转
-
- 示例
- 效果
- 相机自动旋转
-
-
- 示例
- 展示效果
-
- 实现由远到近的雾
-
- 示例
- 展示效果
- Three.js 环境贴图应用
-
- 示例
- 展示效果
- 实现物体反光和阴影(点光源,环境光源)
-
- 光源
- 接受光源/投射效果(阴影)
-
- 示例
- 效果
- 7. 总结练习
-
- 控制移动思想
- 示例
- 效果
- 8. 总结知识点
什么是 three.js
Three.js
是一个用于在网页上创建和展示 3D
图形的 JavaScript
库。它简化了 WebGL
的复杂性,为开发者提供了一组易于使用的 API
,使得创建、显示和操控 3D
对象变得更加方便。以下是对 Three.js 的更详细解释:
为什么使用 three.js
解决了在前端开发中实现 3d 效果的繁琐问题
- 封装 WebGL:WebGL 是一个用于在浏览器内呈现
3D
图形的低级API
,它提供了强大的功能,但学习曲线陡峭。Three.js 封装了 WebGL 的许多复杂性,提供了更简单的接口。 - 易于使用的 API:开发者可以使用简单的函数和对象来创建和操控 3D 场景,而不需要深入理解 WebGL 的细节。
- 快速原型:由于其易用性,开发者能够快速创建和测试 3D 原型,缩短了开发周期。
使用 Three.js
1. 创建场景
在 Three.js
中,Scene
类是构建 3D
环境的基础组件。它充当所有 3D
对象(例立方体、球体、灯光、相机等)的容器,并管理这些对象的渲染。
示例
const scene = new THREE.Scene();
2.创建相机
- 在
Three.js
中,PerspectiveCamera
类用于创建透视相机,它能够模拟人眼的视角,让场景中的物体在视觉上具有深度感。透视相机是 3D 图形中常用的一种相机类型,尤其适用于展示真实世界中的场景。 - 在 Three.js 的所有类中,position 属性用于修改物体在三维空间中的坐标。通过设置 position,我们可以控制相机或其他对象在 X、Y 和 Z 轴上的位置。这使得我们能够灵活地决定视角和观察点,进而影响最终的渲染效果。通过调整相机的位置,我们可以改变观察者的视角,以便获得不同的视觉体验。
示例
const camera = new THREE.PerspectiveCamera();
camera.position.z = 10;
camera.position.y = 2;
3. 创建立方体并添加网格地面
BoxGeometry
是Three.js
中用于创建立方体的一个类。构造函数接受三个参数,分别表示立方体的宽度、高度和深度。MeshBasicMaterial
是一种材质类型,它用于定义 3D 对象的外观。与其他材质不同,MeshBasicMaterial
不受光照影响,因此它总是以定义的颜色显示,无论场景中的光照条件如何。Mesh
是Three.js
中用于创建网格的一个类。Mesh 对象结合了几何体(如 BoxGeometry)和材质(如 MeshBasicMaterial)来构建可视的 3D 物体。通过将几何体和材质结合,Mesh 表示一个具有具体形状和视觉外观的三维对象,可以在场景中进行操作和渲染。
示例
//创建立方体
const geometry = new THREE.BoxGeometry(1, 1, 1);
//设置立方体的颜色
const material = new THREE.MeshBasicMaterial({ color: 0x888 });
//创建网格并把立方体放进去
const cube = new THREE.Mesh(geometry, material);
//设置立方体的位置在可视范围内
cube.position.set(0, 3, 0);
//添加网格地面
const gridHelper = new THREE.GridHelper(10, 10);
//把立方体和网格地面加入场景中
scene.add(cube);
scene.add(gridHelper);
提示
GridHelper
是 Three.js
提供的一个辅助类,用于在场景中生成一个可视化的网格。它的主要功能是帮助开发者和设计师在 3D 空间中定位和对齐对象。GridHelper 的网格通常由线条构成,便于快速判断场景的坐标和对象的位置。
数字代表的含义:
- 第一个参数定义了网格的边长,即网格范围的大小。
- 第二个参数决定了每个维度上将网格细分为多少个单元,影响网格的密度和视觉清晰度。
5. 创建渲染器
在 Three.js
中,WebGLRenderer
是主要的渲染器,它利用 WebGL
技术来在浏览器中绘制高效的 3D
图形。
示例
const renderer = new THEE.WebGLRenderer();
//渲染到id名为container的容器里面
document.getElemnetById("container").appendChild(renderer.domElement);
//调整窗口的大小
renderer.setSize(window.innerWidth, window.innerHeight);
//刚才创建的场景和立方体放进来
renderer.render(scene, camera);
6. 添加效果(移动/雾/相机跟随物体/背景)
自动旋转
- 让立方体自动旋转,可以通过调整
Mesh
对象的rotation
属性来实现。在onMounted
中定义一个名为animate
的函数,该函数内使用requestAnimationFrame(animate)
实现持续的动画循环,并在每帧中更新
示例
const animate = () => {
requestAnimationFrame(animate);
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
//重新放进来
renderer.render(scene, camera);
};
animate();
效果
相机自动旋转
- 为了实现相机的自动旋转,可以使用
OrbitControls
类。该类提供了autoRotate
属性,启用此属性后,相机将自动旋转。此外,可以通过autoRotateSpeed
属性设置旋转的速度,以控制相机自转的快慢。
示例
const controls = new OrbitControls(camera, renderer.domElement);
// 对轨道控制器改变时候进行监听
controls.addEventListener("change", function () {
console.log("触发change");
});
// 添加阻尼
controls.enableDamping = true;
controls.dampingFactor = 0.01;
// 自动旋转
controls.autoRotate = true;
controls.autoRotateSpeed = 0.5;
// 进行渲染
// renderer.render(scene, camera);
// 让立方体动起来
function animate() {
// 告诉浏览器——你希望执行一个动画,并且要求浏览器在下次重绘之前调用指定的回调函数更新动画。该方法需要传入一个回调函数作为参数,该回调函数会在浏览器下一次重绘之前执行。
requestAnimationFrame(animate);
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
// 轨道控制器更新
controls.update();
renderer.render(scene, camera);
}
animate();
展示效果
实现由远到近的雾
- 为了实现 场景由远到近的雾 可以使用
Three.js
中的Fog
类来添加
示例
scene.fog = new THREE.Fog(0xcccccc, 10, 15);
展示效果
Three.js 环境贴图应用
- 使用
THREE.CubeTextureLoader
加载 6 面环境贴图 - 同时应用于场景背景和球体材质
- 实现全景天空盒+环境反射效果
示例
/**
* 立方体贴图加载
* 图片顺序:右(x+)、左(x-)、上(y+)、下(y-)、后(z+)、前(z-)
* 注意:路径需要替换为实际资源目录
*/
const cubleTExture = new THREE.CubeTextureLoader()
.setPath("/") // 纹理资源目录路径
.load([
"04.jpg",
"01.jpg", // 右/左
"05.jpg",
"02.jpg", // 上/下
"06.jpg",
"03.jpg", // 后/前
]);
// 将立方体贴图设置为场景背景(全景天空盒效果)
scene.background = cubleTExture;
/**
* 创建带环境贴图的球体
* 参数说明:
* SphereGeometry(半径, 宽度分段, 高度分段)
* MeshBasicMaterial 基础材质支持环境贴图
*/
const sphere = new THREE.SphereGeometry(1); // 单位半径的球体
const material = new THREE.MeshBasicMaterial({
envMap: cubleTExture, // 材质反射环境贴图
});
scene.add(sphere); // 注:原代码中的cube应为sphere
展示效果
实现物体反光和阴影(点光源,环境光源)
受光材质
- 在
Three.js
中,有一个材质类叫MeshPhongMaterial
。该材质能够通过光源影响其外观,这意味着它适合于需要呈现高光和材质细节的场景。使用MeshPhongMaterial
时,必须为场景添加光源,以便正确地渲染出材质的反射效果和光影变化。
光源
- AmbientLight 是环境光,它接受两个参数:第一个是光的颜色,第二个是光的强度。
- PointLight 是点光源,它接受三个参数:第一个是光的颜色,第二个是光的强度,第三个是光的衰减距离(或范围)。
接受光源/投射效果(阴影)
- 在
Mesh
中 有receiveshadow
和castshadow
分别是 接受光源和投射阴影
示例
const meterial = new THREE.MeshPhongMaterial({
color: 0x00ff00,
shininess: 1000,
});
// 创建MESH
const cubezft = new THREE.Mesh(zft, meterial);
cubezft.position.set(0, 0.5, 0);
//让物体接受光源
cubezft.receiveShadow = true;
//物体投射效果
cubezft.castShadow = true;
const light = new THREE.AmbientLight(0xffffff, 1);
const lightD = new THREE.PointLight(0xffffff, 1000, 100);
lightD.position.set(5, 3, 5);
lightD.castShadow = true;
scene.add(light);
scene.add(cubezft);
//添加点光源
scene.add(lightD);
//创建地面
const meshFloor = new THREE.Mesh(
//创建地面接受两个参数长宽
new THREE.PlaneGeometry(20, 20),
new THREE.MeshPhongMaterial({
color: 0x1b5e20,
side: THREE.DoubleSide, //双面都显示
})
);
//设置位置
meshFloor.position.set(0, 0, -1);
//设置旋转90%
meshFloor.rotation.x -= Math.PI / 2;
//地面也要接受光源
meshFloor.receiveShadow = true;
scene.add(meshFloor);
效果
7. 总结练习
新知识
- 平移属性
translate
有三个值X
Y
Z
接受一个参数 表示平移的单位
控制移动思想
- 使用键盘侦听事件
@keyDOwn
在此事件中有一个参数 里面包含key
和keyCode
两个对象key
输出你所点击的键盘 比如我点击 a 它的值为akeyCode
的是以 ASCll码 来存储的 比如 我点击的是a
则输出 65 - 使用if判断(也可以使用switch) 判断 你点击的键盘COde值 我使用 wasd来控制前后左右移动 只要判断它对应的code值 然后 使用平移属性
translate
进行一系列的操作
如何让场景跟着移动
首先要让相机看向物体 camera.lookAt
接受三个参数 这里 我直接使用 物体的坐标传入 position
然后 让相机跟随物体 设置 相机位置实时 跟着物体 的坐标 这里我使用的是第三人称的效果 在原有物体的y轴+1 还有x轴加4 可以获得第三视角
示例
const up = (event) => {
console.log(event.keyCode);
console.log(event.key);
if (event.key === "ArrowUp") {
cubezft.translateY(0.1);
} else if (event.key == "ArrowDown") {
cubezft.translateY(-0.1);
}else if(event.key === 'ArrowLeft'){
cubezft.rotation.y +=0.1
}
if (event.keyCode === 65) {
cubezft.translateX(-0.1);
} else if (event.keyCode === 87) {
cubezft.translateZ(-0.1);
} else if (event.keyCode === 68) {
cubezft.translateX(0.1);
} else if (event.keyCode === 83) {
cubezft.translateZ(0.1);
}else{
return
}
camera.lookAt(cubezft.position);
camera.position.set(
cubezft.position.x,
cubezft.position.y + 1,
cubezft.position.z + 4
);
};
效果
8. 总结知识点
名称 | 属性 | 用法 |
---|---|---|
场景 | THREE.Scene() |
用于添加和管理3D物体 |
相机 | THREE.PerspectiveCamera() |
控制视图视角,实现物体观察或第一人称效果 |
坐标位置 | position |
设置物体位置,接受x、y、z三个坐标参数 |
物体旋转 | rotation |
控制物体旋转,包含x、y、z三个轴向,可接受具体角度或Math.PI值 |
立方体 | THREE.BoxGeometry() |
创建立方体,接受长、宽、高三个参数 |
圆柱体 | THREE.CylinderGeometry() |
创建圆柱体,接受四个参数依次为:顶部半径、底部半径、高度、分段数 |
圆锥 | THREE.ConeGeometry(); |
创建圆锥体。接受三个参数依次为:底部半径,高度,分段数 |
胶囊体 | THREE.CapsuleGeometry() |
创建胶囊体。接受四个参数依次为:半径、柱体长度、帽部分段数、径向分段数 |
球体 | THREE.SphereGeometry |
创建球体。接受一个参数:半径 |
纹理 | THREE.TextureLoader().load() |
加载普通纹理贴图。参数:图片路径 |
背景纹理 | THREE.CubeTextureLoader().setPath("/").load(); |
加载立方体贴图作为全景背景。参数(setPath):图片路径 、参数(load):6张图片路径数组(顺序:右左上下后前) |
自定义矩形 | THREE.PlaneGeometry() |
创建平面,接受四个参数依次为:宽度、高度、宽度分段、高度分段 |
网格 | THREE.Mesh() |
创建3D物体,参数:几何体、材质 |
Phong材质 | THREE.MeshPhongMaterial() |
创建高光材质,参数:color(颜色)、shininess(高光度) |
基础材质 | THREE.MeshBasicMaterial() |
创建不受光照影响的材质,参数:color(颜色) |
标准材质 | THREE.MeshStandardMaterial() |
创建PBR标准材质,参数:roughness(粗糙度)、metalness(金属度) |
物理材质 | THREE.MeshPhysicalMaterial() |
创建高级PBR材质,参数:clearcoat(清漆层)、transmission(透光率) |
Lambert材质 | THREE.MeshLambertMaterial() |
创建无高光的漫反射材质,参数:color(颜色) |
环境光 | THREE.AmbientLight() |
创建环境光,接受两个参数依次为:颜色、强度 |
点光源 | THREE.PointLight() |
创建点光源,接受四个参数依次为:颜色、强度、距离、衰减 |
平行光 | THREE.DirectionalLight() |
创建平行光,接受两个参数依次为:颜色、强度 |
聚光灯 | THREE.SpotLight() |
创建聚光灯,接受六个参数依次为:颜色、强度、距离、角度、衰减、半影 |
接受光源 | Mesh.receiveShadow |
设置物体是否接收阴影,布尔值 |
投射阴影 | Mesh.castShadow |
设置物体是否投射阴影,布尔值 |
使用纹理 | THREE.MeshStandardMaterial({map: texture}) |
将纹理应用到材质,参数:纹理对象 |
阴影贴图 | renderer.shadowMap.enabled = true |
启用渲染器的阴影渲染功能 |