Three.js 文档:https://threejs.org/
哔哩哔哩配套视频学习教程地址:https://www.bilibili.com/video/BV1HPYQz7Ed2?spm_id_from=333.788.videopod.episodes&vd_source=628c735d0423e2bd1153ac15c47d3d87
首先要清楚我们上一篇文中绘制的立方体在 threejs 中的角色是“物体”,具体讲是网格物体 (Mesh:https://threejs.org/docs/?q=Mesh#api/zh/objects/Mesh)。
通过阅读 threejs 网格物体相关文档内容,了解到所有物体都继承的 Object3D 类(文档地址:https://threejs.org/docs/index.html#api/zh/core/Object3D)。
那么通过 Object3D 的API文档,我们知道可以通过以下三个属性来移动、旋转、缩放物体。
这三个属性都可以通过设置属性值,或者调用属性的 set 方法来变换物体。下面逐个进行介绍及实践应用。
position 属性的值为三维向量 Vector3(x, y, z),默认值为(0, 0, 0)。
语法:
cube.position.x = 5;
// 或
cube.position.set(5, 0, 0);
示例:将立方体沿 x 轴移动5个单位,完整示例代码如下:
// 引入 three.js
import * as THREE from 'three';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
// 场景,摄像机,渲染器
let scene, camera, renderer;
// 轨道控制器
let controls;
// 立方体
let cube;
// 初始化三要素
function init() {
// 1. 创建场景对象
scene = new THREE.Scene();
// 2. 创建摄像机对象
// 参数1:垂直角度(建议75),视野范围
// 参数2:宽高比(建议与画布相同宽高),物体绘制比例
// 参数3:近截面距离摄像机距离
// 参数4:远截面距离摄像机距离
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
// 移动摄像机 z 轴 5 个单位(默认摄像机和物体的坐标轴的都在原点)
camera.position.z = 5;
// 3. 创建渲染器
renderer = new THREE.WebGLRenderer({
antialias: true, // 开启抗锯齿 - 优化
});
renderer.setSize(window.innerWidth, window.innerHeight); // 设置画布大小
document.body.append(renderer.domElement); // 添加到DOM显示
}
// 创建立方体
function createCube() {
// 1. 创建图形,宽深高为 1 单位(立体缓冲几何体)
const geometry = new THREE.BoxGeometry(1, 1, 1);
// 2. 创建材质,颜色为绿色 0x00ff00 (网格基础材质 - 线面纯颜色描绘表面)
const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
// 3. 创建网格物体对象,传入图形和材质(网格物体对象)
cube = new THREE.Mesh(geometry, material);
// 4. 把物体加入到场景中
scene.add(cube);
}
// 创建轨道控制器
function createControls() {
controls = new OrbitControls(camera, renderer.domElement);
// 设置阻尼效果 true / false
controls.enableDamping = true;
// 设置是否自动旋转 true / false
controls.autoRotate = false;
}
/**
* 渲染循环
*/
function renderLoop() {
renderer.render(scene, camera);
// 手动 JS 代码更新过摄像机信息,必须调用轨道控制器 update 方法
controls.update();
// 根据当前计算机浏览器刷新帧率(默认 60 次/秒),不断递归调用此函数渲染最新的画面状态
// 好处:当前页面切换到后台,暂停递归
requestAnimationFrame(renderLoop);
}
// 添加坐标轴辅助对象
function createHelper() {
/**
* 用于简单模拟3个坐标轴的对象.
* 红色代表 X 轴. 绿色代表 Y 轴. 蓝色代表 Z 轴.
*/
const axesHelper = new THREE.AxesHelper(5);
scene.add(axesHelper);
}
/**
* 优化 - 适配场景大小
*/
function resizeRender() {
window.addEventListener('resize', () => {
renderer.setSize(window.innerWidth, window.innerHeight);
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
});
}
function moveCube() {
// 将立方体在 x 轴移动 5 个单位
cube.position.x = 5;
}
// 初始化元素
init();
// 创建轨道控制器
createControls();
// 添加坐标轴
createHelper();
// 场景自适应适配
resizeRender();
// 创建立方体
createCube();
// 变换立方体
moveCube();
// 渲染循环
renderLoop();
上面的示例代码中 moveCube 方法为新增实现 position 移动立方体的代码实现,效果如下:
由于摄像机还在原点的位置,所以移动后是一种斜视的效果。
rotation 属性值为 Eular 角(欧拉角)对象(弧度制)。
语法:
cube.rotation.z = Math.PI / 4;
// 或
cube.rotation.set(0, 0, Math.PI / 4)
示例:将立方体绕 z 轴旋转45度,完整示例代码如下:
// 引入 three.js
import * as THREE from 'three';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
// 场景,摄像机,渲染器
let scene, camera, renderer;
// 轨道控制器
let controls;
// 立方体
let cube;
// 初始化三要素
function init() {
// 1. 创建场景对象
scene = new THREE.Scene();
// 2. 创建摄像机对象
// 参数1:垂直角度(建议75),视野范围
// 参数2:宽高比(建议与画布相同宽高),物体绘制比例
// 参数3:近截面距离摄像机距离
// 参数4:远截面距离摄像机距离
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
// 移动摄像机 z 轴 5 个单位(默认摄像机和物体的坐标轴的都在原点)
camera.position.z = 5;
// 3. 创建渲染器
renderer = new THREE.WebGLRenderer({
antialias: true, // 开启抗锯齿 - 优化
});
renderer.setSize(window.innerWidth, window.innerHeight); // 设置画布大小
document.body.append(renderer.domElement); // 添加到DOM显示
}
// 创建立方体
function createCube() {
// 1. 创建图形,宽深高为 1 单位(立体缓冲几何体)
const geometry = new THREE.BoxGeometry(1, 1, 1);
// 2. 创建材质,颜色为绿色 0x00ff00 (网格基础材质 - 线面纯颜色描绘表面)
const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
// 3. 创建网格物体对象,传入图形和材质(网格物体对象)
cube = new THREE.Mesh(geometry, material);
// 4. 把物体加入到场景中
scene.add(cube);
}
// 创建轨道控制器
function createControls() {
controls = new OrbitControls(camera, renderer.domElement);
// 设置阻尼效果 true / false
controls.enableDamping = true;
// 设置是否自动旋转 true / false
controls.autoRotate = false;
}
/**
* 渲染循环
*/
function renderLoop() {
renderer.render(scene, camera);
// 手动 JS 代码更新过摄像机信息,必须调用轨道控制器 update 方法
controls.update();
// 根据当前计算机浏览器刷新帧率(默认 60 次/秒),不断递归调用此函数渲染最新的画面状态
// 好处:当前页面切换到后台,暂停递归
requestAnimationFrame(renderLoop);
}
// 添加坐标轴辅助对象
function createHelper() {
/**
* 用于简单模拟3个坐标轴的对象.
* 红色代表 X 轴. 绿色代表 Y 轴. 蓝色代表 Z 轴.
*/
const axesHelper = new THREE.AxesHelper(5);
scene.add(axesHelper);
}
/**
* 优化 - 适配场景大小
*/
function resizeRender() {
window.addEventListener('resize', () => {
renderer.setSize(window.innerWidth, window.innerHeight);
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
});
}
function moveCube() {
// 将立方体绕 z 轴旋转45度
// cube.rotation.z = Math.PI / 4;
cube.rotation.set(0, 0, Math.PI / 4);
}
// 初始化元素
init();
// 创建轨道控制器
createControls();
// 添加坐标轴
createHelper();
// 场景自适应适配
resizeRender();
// 创建立方体
createCube();
// 变换立方体
moveCube();
// 渲染循环
renderLoop();
上面的示例代码中 moveCube 方法为新增实现 rotation 旋转立方体的代码实现,效果如下:
但是我们无法看出旋转方向,实际上在轴的正方向来看物体旋转,默认是绕着轴进行逆时针旋转。为了验证,下面提供一个动态旋转效果测试示例:
这样我们就很直观的看出旋转方向了,实现方法就是在上面的旋转示例代码中的 渲染循环方法 renderLoop 中增加了一行代码 cube.rotation.z += 0.01
,修改后 renderLoop 方法的完整代码如下:
/**
* 渲染循环
*/
function renderLoop() {
renderer.render(scene, camera);
// 手动 JS 代码更新过摄像机信息,必须调用轨道控制器 update 方法
controls.update();
cube.rotation.z += 0.01
// 根据当前计算机浏览器刷新帧率(默认 60 次/秒),不断递归调用此函数渲染最新的画面状态
// 好处:当前页面切换到后台,暂停递归
requestAnimationFrame(renderLoop);
}
scale 属性的值为三维向量 Vector3(x, y, z),默认值为(1, 1, 1)。
示例语法:
cube.scale.y = 2;
// 或
cube.scale.set(1, 2, 1)
示例:将立方体在 y 轴放大一倍,完整示例代码如下:
// 引入 three.js
import * as THREE from 'three';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
// 场景,摄像机,渲染器
let scene, camera, renderer;
// 轨道控制器
let controls;
// 立方体
let cube;
// 初始化三要素
function init() {
// 1. 创建场景对象
scene = new THREE.Scene();
// 2. 创建摄像机对象
// 参数1:垂直角度(建议75),视野范围
// 参数2:宽高比(建议与画布相同宽高),物体绘制比例
// 参数3:近截面距离摄像机距离
// 参数4:远截面距离摄像机距离
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
// 移动摄像机 z 轴 5 个单位(默认摄像机和物体的坐标轴的都在原点)
camera.position.z = 5;
// 3. 创建渲染器
renderer = new THREE.WebGLRenderer({
antialias: true, // 开启抗锯齿 - 优化
});
renderer.setSize(window.innerWidth, window.innerHeight); // 设置画布大小
document.body.append(renderer.domElement); // 添加到DOM显示
}
// 创建立方体
function createCube() {
// 1. 创建图形,宽深高为 1 单位(立体缓冲几何体)
const geometry = new THREE.BoxGeometry(1, 1, 1);
// 2. 创建材质,颜色为绿色 0x00ff00 (网格基础材质 - 线面纯颜色描绘表面)
const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
// 3. 创建网格物体对象,传入图形和材质(网格物体对象)
cube = new THREE.Mesh(geometry, material);
// 4. 把物体加入到场景中
scene.add(cube);
}
// 创建轨道控制器
function createControls() {
controls = new OrbitControls(camera, renderer.domElement);
// 设置阻尼效果 true / false
controls.enableDamping = true;
// 设置是否自动旋转 true / false
controls.autoRotate = false;
}
/**
* 渲染循环
*/
function renderLoop() {
renderer.render(scene, camera);
// 手动 JS 代码更新过摄像机信息,必须调用轨道控制器 update 方法
controls.update();
// 根据当前计算机浏览器刷新帧率(默认 60 次/秒),不断递归调用此函数渲染最新的画面状态
// 好处:当前页面切换到后台,暂停递归
requestAnimationFrame(renderLoop);
}
// 添加坐标轴辅助对象
function createHelper() {
/**
* 用于简单模拟3个坐标轴的对象.
* 红色代表 X 轴. 绿色代表 Y 轴. 蓝色代表 Z 轴.
*/
const axesHelper = new THREE.AxesHelper(5);
scene.add(axesHelper);
}
/**
* 优化 - 适配场景大小
*/
function resizeRender() {
window.addEventListener('resize', () => {
renderer.setSize(window.innerWidth, window.innerHeight);
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
});
}
function moveCube() {
// 将立方体在 y 轴放大一倍
// cube.scale.y = 2
cube.scale.set(1, 2, 1)
}
// 初始化元素
init();
// 创建轨道控制器
createControls();
// 添加坐标轴
createHelper();
// 场景自适应适配
resizeRender();
// 创建立方体
createCube();
// 变换立方体
moveCube();
// 渲染循环
renderLoop();
上面的示例代码中 moveCube 方法为新增实现 scale 缩放立方体的代码实现,效果如下:
至此本文结束了,希望有助于您!
🔥BuildAdmin是一个永久免费开源,无需授权即可商业使用,且使用了流行技术栈快速创建商业级后台管理系统。