OrbitControls 轨道控制器
🎯 引言
好用的 3D 页面都允许用户“动手”:拖一拖转着看、滚轮拉远近。如果自己监听鼠标事件再换算成相机位置,要写不少数学代码。Three.js 官方提供了现成的 OrbitControls(轨道控制器),几行代码就能让场景支持鼠标交互。学完这篇文章,你能给场景接上 OrbitControls,并掌握阻尼、自动旋转等常用配置。
🧱 什么是 OrbitControls
OrbitControls 是 Three.js 自带的相机控制器,装上之后用户就能:
- 左键拖拽:围绕场景中心旋转视角。
- 滚轮滚动:拉近、拉远相机。
- 右键拖拽:平移画面。
“轨道”这个名字很形象:相机始终围着目标点转,就像卫星在轨道上围着地球转。
🚀 引入方式
OrbitControls 不在 Three.js 核心代码里,而是放在附加组件目录中,通过 three/addons/ 这个别名引入:
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
three/addons 别名的解析。Vite、Webpack5 等现代工具都内置支持,直接用即可,不需要单独安装其他包。🛠 接入控制器
创建时传入相机和渲染器的画布,它就接管了鼠标事件:
<template>
<div ref="containerRef" class="container"></div>
</template>
<script setup>
import { onMounted, ref } from 'vue';
import * as THREE from 'three';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
const containerRef = ref(null);
onMounted(() => {
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, 320 / 240, 0.1, 1000);
camera.position.set(2, 2, 4);
camera.lookAt(0, 0, 0);
const cube = new THREE.Mesh(
new THREE.BoxGeometry(1.5, 1.5, 1.5),
new THREE.MeshStandardMaterial({ color: 0x44aa88 })
);
scene.add(cube);
scene.add(new THREE.AmbientLight(0xffffff, 0.5));
const directionalLight = new THREE.DirectionalLight(0xffffff, 1.5);
directionalLight.position.set(3, 5, 4);
scene.add(directionalLight);
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(320, 240);
containerRef.value.appendChild(renderer.domElement);
// 创建控制器:传入相机 + 渲染器的画布
const controls = new OrbitControls(camera, renderer.domElement);
const animate = () => {
requestAnimationFrame(animate);
controls.update(); // 每帧更新控制器状态
renderer.render(scene, camera);
};
animate();
});
</script>
<style scoped>
.container {
width: 320px;
height: 240px;
}
</style>
相比上一篇的动画代码,改动只有三处:
- 引入
OrbitControls。 new OrbitControls(camera, renderer.domElement)创建控制器。- 渲染循环里调用
controls.update()。
用户拖动画布时,OrbitControls 会自动修改相机的位置和朝向,我们什么都不用算。
🧱 常用配置
const controls = new OrbitControls(camera, renderer.domElement);
controls.enableDamping = true; // 阻尼:松手后惯性滑动一小段,手感更顺滑
controls.dampingFactor = 0.05; // 阻尼系数,越小滑得越远
controls.autoRotate = true; // 自动旋转:无人操作时相机自己绕场转
controls.autoRotateSpeed = 1.0; // 自动旋转速度
controls.minDistance = 2; // 最多只能拉近到 2,防止穿进物体里
controls.maxDistance = 20; // 最多只能拉远到 20,防止场景缩成一个小点
几个使用经验:
enableDamping建议常开,开了之后必须在渲染循环里调用controls.update(),否则阻尼不生效。autoRotate适合产品展示页:用户不动时场景自己慢慢转,用户上手拖拽时会自动暂停。minDistance/maxDistance是体验保护,建议设置,避免用户把相机拉丢。
🧾 小节总结
- OrbitControls 提供鼠标交互:左键旋转、滚轮缩放、右键平移。
- 从
three/addons/controls/OrbitControls.js引入,无需额外安装。 - 创建时传入相机和
renderer.domElement,循环里调用controls.update()。 enableDamping提供顺滑惯性,必须配合controls.update()使用。autoRotate自动旋转展示;minDistance/maxDistance限制缩放范围。
❓ 知识问答
Q1:OrbitControls 和我自己写的相机动画冲突吗?
会。两者都想控制相机,画面会来回打架。用了 OrbitControls,就把相机的控制权交给它;物体自己的动画(自转、浮动)不受影响,可以正常写。
Q2:右键平移想禁用怎么办?
设 controls.enablePan = false。同理还有 enableRotate(旋转)、enableZoom(缩放),都可以单独开关。
Q3:控制器监听的事件会自己销毁吗?
不会。组件卸载时要调用 controls.dispose() 移除事件监听,写法在下一篇“Vue3 实战”里统一演示。
Q4:手机端能用 OrbitControls 吗?
可以。它同时支持触屏:单指旋转、双指缩放、双指平移,不需要额外配置。
🧪 小练习
给上一篇的“跳动的球”装上交互:
- 引入 OrbitControls,开启阻尼。
- 设置
minDistance = 3、maxDistance = 15。 - 开启
autoRotate,然后拖拽一下画布,观察自动旋转暂停又恢复的过程。
<template>
<div ref="containerRef" class="container"></div>
</template>
<script setup>
import { onMounted, ref } from 'vue';
import * as THREE from 'three';
// 请在这里引入 OrbitControls
const containerRef = ref(null);
onMounted(() => {
// 请在这里编写代码
});
</script>
<style scoped>
.container {
width: 320px;
height: 240px;
}
</style>
🎉 恭喜你已经掌握轨道控制器啦!下一篇我们把前面学到的知识整合起来,封装一个可以在 Vue3 项目里反复使用的 3D 组件。
