news 2026/7/4 5:30:08

Three.js 轨道控制器教程

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Three.js 轨道控制器教程

轨道控制器 ·Orbit Controls· ▶ 在线运行案例

  • 案例合集:三维可视化功能案例(threehub.cn)
  • 开源仓库github地址:https://github.com/z2586300277/three-cesium-examples
  • 400个案例代码:网盘链接

你将学到什么

  • OrbitControls全部常用配置项含义
  • 阻尼 enableDamping与每帧update()的关系
  • 距离 / 方位角 / 极角限制如何约束观察范围
  • controls.target轨道中心点的意义

效果说明

贴图平面 + 网格/坐标轴辅助。右侧 GUI 列出 OrbitControls几乎所有公开参数,拖动滑块即可感受:

  • 左键旋转、滚轮缩放、右键平移(可单独开关)
  • 自动旋转、阻尼惯性
  • 最近/最远距离、水平/垂直角度上下限
  • zoomToCursor以鼠标位置为缩放中心

核心概念

OrbitControls 在做什么?

OrbitControls 不改变物体,而是改变相机 position观察目标 target,使相机围绕target(默认原点)做轨道运动

target (观察中心)

● /│\ / │ \ 相机 ● │ 轨道球面 │ 左键拖拽 → 改变方位角/极角 滚轮 → 改变与 target 距离 右键 → 平移 target + 相机

const controls = new OrbitControls(camera, renderer.domElement);

controls.target.set(0, 0, 0); // 轨道中心,默认 (0,0,0)

阻尼 autoRotate

| 属性 | 作用 | |------|------| |enableDamping| 开启惯性,松手后缓慢停止 | |dampingFactor| 阻尼系数,通常 0.05~0.1 | |autoRotate| 自动绕 target 水平旋转 | |autoRotateSpeed| 自动旋转速度 |

controls.enableDamping = true;

controls.dampingFactor = 0.05;

function animate() { controls.update(); // 阻尼和 autoRotate 必须每帧调用 renderer.render(scene, camera); }

::: warning 开enableDampingautoRotate却不在 rAF 里controls.update()→ 阻尼无效、自动旋转卡住。 :::

距离与角度限制

| 属性 | 限制内容 | |------|---------| |minDistance/maxDistance| 相机到 target 的最小/最大距离(缩放范围) | |minAzimuthAngle/maxAzimuthAngle| 水平绕圈角度(弧度) | |minPolarAngle/maxPolarAngle| 垂直角度:0=正上方,π/2=水平,π=正下方 | |minTargetRadius/maxTargetRadius| target 移动半径限制(较少用) |

典型用法:建筑漫游常设maxPolarAngle = Math.PI / 2,防止相机钻到地底下。

交互开关与速度

controls.enableRotate = true; // 左键旋转

controls.enableZoom = true; // 滚轮缩放 controls.enablePan = true; // 右键平移 controls.rotateSpeed = 1.0; controls.zoomSpeed = 1.0; controls.panSpeed = 1.0; controls.zoomToCursor = true; // 滚轮以鼠标指向点为缩放中心

两种渲染策略

1. 持续 rAF(本案例,配合阻尼/autoRotate)
function animate() {

requestAnimationFrame(animate); controls.update(); renderer.render(scene, camera); }

2. 按需渲染(静态场景省电)
controls.addEventListener('change', () => renderer.render(scene, camera));

// 无阻尼时可不开 rAF

实现步骤

  • Scene + Camera + Renderer
  • new OrbitControls(camera, renderer.domElement)
  • rAF 中controls.update()+ render
  • GUI 绑定全部 controls 属性,target.x/y/z.listen()观察 Orbit 变化
  • GridHelper + AxesHelper 辅助理解轨道
  • 代码要点

    import * as THREE from 'three'

    import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js' import { GUI } from "three/addons/libs/lil-gui.module.min.js"

    const box = document.getElementById('box')

    const scene = new THREE.Scene()

    const camera = new THREE.PerspectiveCamera(50, box.clientWidth / box.clientHeight, 0.1, 1000)

    camera.position.set(0, 1, 4)

    const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true, logarithmicDepthBuffer: true })

    renderer.setSize(box.clientWidth, box.clientHeight)

    box.appendChild(renderer.domElement)

    const controls = new OrbitControls(camera, renderer.domElement)

    const geomerty = new THREE.PlaneGeometry(1, 1)

    const map = new THREE.TextureLoader().load(HOST + 'files/author/KallkaGo.jpg')

    const material = new THREE.MeshBasicMaterial({ map , color: 0xf2f2f2, side: THREE.DoubleSide })

    const mesh = new THREE.Mesh(geomerty, material)

    scene.add(mesh)

    animate()

    function animate() {

    requestAnimationFrame(animate)

    controls.update()

    renderer.render(scene, camera)

    }

    scene.add(new THREE.AxesHelper(10), new THREE.GridHelper(10, 10))

    const folder = new GUI()

    folder.add(controls, 'autoRotate').name('自动旋转')

    folder.add(controls, 'autoRotateSpeed').name('自动旋转速度')

    folder.add(controls, 'enableDamping').name('阻尼')

    folder.add(controls, 'dampingFactor').name('阻尼系数').min(0).max(1)

    folder.add(controls, 'minDistance').name('最小距离')

    folder.add(controls, 'maxDistance').name('最大距离')

    folder.add(controls, 'maxAzimuthAngle', -2Math.PI, Math.PI2).name('水平旋转上限')

    folder.add(controls, 'minAzimuthAngle', -2Math.PI, Math.PI2).name('水平旋转下限')

    folder.add(controls, 'maxPolarAngle', 0, Math.PI).name('垂直旋转上限')

    folder.add(controls, 'minPolarAngle', 0, Math.PI).name('垂直旋转下限')

    folder.add(controls, 'maxTargetRadius').name('目标移动上限')

    folder.add(controls, 'minTargetRadius').name('目标移动下限')

    folder.add(controls, 'enablePan').name('平移')

    folder.add(controls, 'panSpeed').name('平移速度')

    folder.add(controls, 'enableRotate').name('旋转')

    folder.add(controls, 'rotateSpeed').name('旋转速度')

    folder.add(controls, 'enableZoom').name('缩放')

    folder.add(controls, 'zoomSpeed').name('缩放速度')

    folder.add(controls, 'zoomToCursor').name('光标为缩放中心')

    folder.add(controls.target, 'x').name('目标位置x').listen()

    folder.add(controls.target, 'y').name('目标位置y').listen()

    folder.add(controls.target, 'z').name('目标位置z').listen()

    folder.add({ '重置': () => folder.reset()}, '重置')

    完整源码:GitHub

    小结

    • 本文提供轨道控制器完整 Three.js 源码与在线 Demo,建议先运行案例再改 uniform/参数做二次实验
    • 更多 Three.js 实战案例见 three-cesium-examples 合集 与 GitHub 开源仓库
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/1 1:59:08

级联故障的防火墙:微服务容错设计的核心模式与 Resilience4j 实战

级联故障的防火墙:微服务容错设计的核心模式与 Resilience4j 实战 一、从单点超时到雪崩效应:微服务故障传播的链式反应 微服务架构的核心优势是独立部署和独立伸缩,但其代价是服务间调用的网络依赖大幅增加。一个典型的电商下单流程可能涉及…

作者头像 李华
网站建设 2026/7/4 1:23:08

3分钟搞定Axure RP汉化:免费中文界面完整教程指南

3分钟搞定Axure RP汉化:免费中文界面完整教程指南 【免费下载链接】axure-cn Chinese language file for Axure RP. Axure RP 简体中文语言包。支持 Axure 11、10、9。不定期更新。 项目地址: https://gitcode.com/gh_mirrors/ax/axure-cn 还在为Axure RP的英…

作者头像 李华
网站建设 2026/7/4 1:09:21

量子机器学习与领域感知量子电路的设计与应用

1. 量子机器学习与领域感知量子电路概述量子机器学习(Quantum Machine Learning, QML)作为量子计算与经典机器学习的交叉领域,近年来在图像分类、药物发现和金融预测等任务中展现出独特优势。与传统机器学习不同,QML利用量子态的叠…

作者头像 李华
网站建设 2026/7/4 0:32:45

车载以太网之要火系列:第73篇:L1-001 链路建立时间(二)——判定标准与三个测试循环

上篇我们把L1-001的测试方法拆完了,今天接着把判定标准讲透,然后把三个测试循环放在一起对比——毕竟这三个用例共用同一套统计逻辑,放在一起看更清楚。 📄 翻开规范 书接上篇的截图,规范写了判定公式和限值: Pass criteria: σt ≤ 50 ms tmin > 10 ms + tready …

作者头像 李华