Three.js零基础入门学习笔记二:如何控制轨道控制器、场景大小适配优化

  • 原创
  • 作者:程序员三丰
  • 发布时间:2025-09-26 11:18
  • 浏览量:58
本文进一步介绍如何调整轨道控制器常用的控制相关的属性,从而影响摄像机的展示细节,以及对场景大小动态改变时的适配优化。

Three.js 文档:https://threejs.org/

哔哩哔哩配套视频学习教程地址:https://www.bilibili.com/video/BV1HPYQz7Ed2?spm_id_from=333.788.videopod.episodes&vd_source=628c735d0423e2bd1153ac15c47d3d87

轨道控制器 - 控制

我们可以通过调整配置轨道控制器的相关属性,从而优化影响摄像机的展示细节。主要介绍以下几个部分:

阻尼效果

旋转物体时增加阻尼效果,可以想像一下日常生活的中家具柜门的阻尼效果,与此类似。

那么通过给已经创建的轨道控制对象设置属性enableDamping = true 来开启阻尼效果,默认不开启阻尼效果。

另外可以通过设置属性 dampingFactor 的值为一个 Float 类型的浮点值,来设置阻尼惯性的大小,默认值 0.05。

具体代码实现,定位 main.js 文件的 createControls 方法,做如下修改:

// file: src/main.js

// 创建轨道控制器
function createControls() {
  controls = new OrbitControls(camera, renderer.domElement);

  // 开启阻尼效果
  controls.enableDamping = true;
}

有无阻尼效果对比:

自动旋转(相机顺时针旋转)

通过给已经创建的轨道控制对象设置属性autoRotate = true 来开启自动旋转轨道控制器的效果,从而带动摄像机一起旋转。

具体代码实现,定位 main.js 文件的 createControls 方法,做如下修改:

// file: src/main.js

// 创建轨道控制器
function createControls() {
  controls = new OrbitControls(camera, renderer.domElement);

   // 开启阻尼效果
  controls.enableDamping = true;

  // 开启自动旋转
  controls.autoRotate = true;
}

效果如下:

垂直旋转角度范围控制

通过给已经创建的轨道控制对象设置属性minPolarAnglemaxPolarAngle 来控制相机能够垂直旋转的角度的上下限。

  • minPolarAngle:该属性设置能够垂直旋转的角度的下限制,范围是 0 到 Math.PI,其默认值为 0 。
  • maxPolarAngle:该属性设置能够垂直旋转的角度的上限,范围是 0 到 Math.PI,其默认值为 Math.PI。

可以通过将二者设置为相同的值来禁用单个轴。

从上图可以看出,0 表示相机在上面,Math.PI 表示相机在下方。

具体代码实现,定位 main.js 文件的 createControls 方法,做如下修改:

// file: src/main.js

// 创建轨道控制器
function createControls() {
  controls = new OrbitControls(camera, renderer.domElement);

   // 开启阻尼效果
  controls.enableDamping = true;

  // 关闭自动旋转
  controls.autoRotate = true;

  // 设置垂直旋转的角度下限,范围是 0 ~ Math.PI,默认 0
  controls.minPolarAngle = 0;

  // 设置垂直旋转的角度上限,范围是 0 ~ Math.PI, 默认 Math.PI
  controls.maxPolarAngle = Math.PI / 2;
}

上面示例代码配置效果(只能向下旋转90度,不能向上旋转)如下:

水平旋转角度范围控制

通过给已经创建的轨道控制对象设置属性minAzimuthAnglemaxAzimuthAngle 来控制相机能够水平旋转的角度的上下限。

  • minAzimuthAngle:该属性设置能够水平旋转的角度的下限,范围是 -2 Math.PI 到 2 Math.PI,其默认值为无穷大 。
  • maxAzimuthAngle:该属性设置能够水平旋转的角度的上限,范围是 -2 Math.PI 到 2 Math.PI,其默认值为无穷大。

可以通过将二者设置为相同的值来禁用单个轴。

具体代码实现,定位 main.js 文件的 createControls 方法,做如下修改:

// file: src/main.js

// 创建轨道控制器
function createControls() {
  controls = new OrbitControls(camera, renderer.domElement);

  // 设置阻尼效果 true / false
  controls.enableDamping = true;

  // 设置是否自动旋转 true / false
  controls.autoRotate = false;

  // 设置垂直旋转的角度下限,范围是 0 ~ Math.PI,默认 0
  controls.minPolarAngle = 0.5 * Math.PI;

  // 设置垂直旋转的角度上限,范围是 0 ~ Math.PI, 默认 Math.PI
  controls.maxPolarAngle = 0.5 * Math.PI;

  // 设置水平旋转的角度的下限,范围是 -2 * Math.PI 到 2 * Math.PI,其默认值为无穷大
  controls.minAzimuthAngle = 0.5 * Math.PI;

  // 设置水平旋转的角度的上限,范围是 -2 * Math.PI 到 2 * Math.PI,其默认值为无穷大
  controls.maxAzimuthAngle = 1.5 * Math.PI;
}

上面示例代码配置效果(禁止垂直旋转,水平旋转不能看到前面,左右后三面可见)如下:

移动范围控制

通过给已经创建的轨道控制对象设置属性minDistancemaxDistance 来控制相机向内或向外移动的最大范围。

  • minDistance:该属性设置能够将相机向内移动多少,其默认值为 0 。
  • maxDistance:该属性设置能够将相机向外移动多少,其默认值为无穷大。

具体代码实现,定位 main.js 文件的 createControls 方法,做如下修改:

// file: src/main.js

// 创建轨道控制器
function createControls() {
  controls = new OrbitControls(camera, renderer.domElement);

  // 设置阻尼效果 true / false
  controls.enableDamping = true;

  // 设置是否自动旋转 true / false
  controls.autoRotate = false;

  // 设置垂直旋转的角度下限,范围是 0 ~ Math.PI,默认 0
  controls.minPolarAngle = 0.5 * Math.PI;

  // 设置垂直旋转的角度上限,范围是 0 ~ Math.PI, 默认 Math.PI
  controls.maxPolarAngle = 0.5 * Math.PI;

  // 设置水平旋转的角度的下限,范围是 -2 * Math.PI 到 2 * Math.PI,其默认值为无穷大
  controls.minAzimuthAngle = 0.5 * Math.PI;

  // 设置水平旋转的角度的上限,范围是 -2 * Math.PI 到 2 * Math.PI,其默认值为无穷大
  controls.maxAzimuthAngle = 1.5 * Math.PI;

  // 设置相机能够向内最小移动多少
  controls.minDistance = 2;

  // 设置相机能够向外最大移动多少
  controls.maxDistance = 10;
}

上面示例代码配置效果如下:

优化 - 适配场景大小

当浏览器窗口尺寸改变时,我们希望场景及其内部物体的尺寸可以自适应。

步骤:

  1. 创建适配函数,监听浏览器 resize 事件;
  2. 调整渲染器画布宽高,摄像机宽高比和更新视椎体空间。

具体代码实现,在 main.js 文件内增加一个 resizeRender 的方法,下面是 main.js 文件的完整代码:

// file: src/main.js

// 引入 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;

  // 设置垂直旋转的角度下限,范围是 0 ~ Math.PI,默认 0
  // controls.minPolarAngle = 0.5 * Math.PI;

  // 设置垂直旋转的角度上限,范围是 0 ~ Math.PI, 默认 Math.PI
  // controls.maxPolarAngle = 0.5 * Math.PI;

  // 设置水平旋转的角度的下限,范围是 -2 * Math.PI 到 2 * Math.PI,其默认值为无穷大
  // controls.minAzimuthAngle = 0.5 * Math.PI;

  // 设置水平旋转的角度的上限,范围是 -2 * Math.PI 到 2 * Math.PI,其默认值为无穷大
  // controls.maxAzimuthAngle = 1.5 * Math.PI;

  // 设置相机能够向内最小移动多少
  // controls.minDistance = 2;

  // 设置相机能够向外最大移动多少
  // controls.maxDistance = 10;
}

/**
 * 渲染循环
 */
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();
  });
}

// 初始化元素
init();

// 创建轨道控制器
createControls();

// 添加坐标轴
createHelper();

// 场景自适应适配
resizeRender();

// 创建立方体
createCube();

// 渲染循环
renderLoop();

效果如下:

尾语(总结)

通过本文的学习,我们要充分理解和体会物体和摄像机的空间立体感,个人觉得这个至关重要,物体是不动的,我们所看到的物理的旋转和位移,实际上是摄像机在移动,只有理解了这个基础且重要的相对概念,才能更好的进行学习。

声明:本文为原创文章,51blog.xyz和作者拥有版权,如需转载,请注明来源于51blog.xyz并保留原文链接:https://www.51blog.xyz/article/94.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