Three.js零基础入门学习笔记三:移动、旋转、缩放立方体

  • 原创
  • 作者:程序员三丰
  • 发布时间:2025-10-16 23:42
  • 浏览量:5
前面两篇文章都是在控制摄像机的移动,位移或者旋转,本文将介绍如何移动物体-立方体。

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文档,我们知道可以通过以下三个属性来移动、旋转、缩放物体。

  • 移动使用 position 属性
  • 旋转使用 rotation 属性
  • 缩放使用 scale 属性

这三个属性都可以通过设置属性值,或者调用属性的 set 方法来变换物体。下面逐个进行介绍及实践应用。

移动 position 属性

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 属性

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 属性

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 缩放立方体的代码实现,效果如下:

尾语

至此本文结束了,希望有助于您!

声明:本文为原创文章,51blog.xyz和作者拥有版权,如需转载,请注明来源于51blog.xyz并保留原文链接:https://www.51blog.xyz/article/95.html

文章归档

推荐文章

buildadmin logo
Thinkphp8 Vue3 Element PLus TypeScript Vite Pinia

🔥BuildAdmin是一个永久免费开源,无需授权即可商业使用,且使用了流行技术栈快速创建商业级后台管理系统。

热门标签

PHP ThinkPHP ThinkPHP5.1 Go Mysql Mysql5.7 Redis Linux CentOS7 Git HTML CSS CSS3 Javascript JQuery Vue LayUI VMware Uniapp 微信小程序 docker wiki Confluence7 学习笔记 uView ES6 Ant Design Pro of Vue React ThinkPHP6.0 chrome 扩展 翻译工具 Nuxt SSR 服务端渲染 scrollreveal.js ThinkPHP8.0 Mac webman 跨域CORS vscode GitHub ECharts Canvas vue3 three.js