更新于 

Controls 控制器

OrbitControls能够控制相机旋转、缩放、平移,
其中提供了不少可以修改的参数。
(本人晕3d,OrbitControls还好,FirstPersonControls开发太蓝瘦了)

OrbitControls 轨道控制器

控制器参数

config

配置参数不少,Threejs里面不少API都是这样,
想不起来就看编译器提示或者官方文档
实在不行看源码也挺好。

  • panSpeed 平移速度
  • rotateSpeed 旋转速度
  • maxDistance 缩放大小
  • enablePan 是否允许平移
  • enableDamping 是否开启阻尼
    -(注意开启之后loop中必须对控制器进行update更新)
  • dampingFactor 阻尼大小
  • autoRotate 自动旋转
  • autoRotateSpeed 自动旋转速度
  • target 焦点
    • 焦点和相机位置重叠会导致控制器失效
    • 之前因为不知道这一点走了不少弯路,恼啊
开启阻尼之后,相机移动丝滑很多
开启阻尼之后,相机移动丝滑很多

自定义控制键

控制键

配置鼠标控制器:

1
2
orbit.mouseButtons.LEFT = THREE.MOUSE.ROTATE
orbit.mouseButtons.RIGHT = THREE.MOUSE.PAN

键盘控制器(注意最后需要将监听器添加到window上):

1
2
3
4
5
6
7
8
orbit.keys = {
LEFT:"ArrowLeft",
UP:"ArrowUp",
RIGHT:"KeyD",
BOTTOM:"KeyS"
}
orbit.listenToKeyEvents(window)
orbit.keyPanSpeed = 20

状态保存

  • saveState() 状态保存
  • reset() 状态重置/读取
1
2
3
4
5
6
window.onkeydown = e => {
if (e.code === 'KeyS')
orbit.saveState()
else if (e.code === 'KeyL')
orbit.reset()
}

限制

  • 水平方位角限制
    • minAzimuthAngle
    • maxAzimuthAngle
  • 垂直方位角限制
    • minPolarAngle
    • maxPolarAngle

TrackballControls 轨迹球控制器

TrackballControlsOrbitControls 非常类似,
根据官方文档的介绍,两种控制器的不同是 TrackballControls无法恒定保持摄像机的up向量
(没看懂)
但两者的适用场景有所不同:

  • OrbitControls 静态平滑的旋转效果,适合用户通过平移旋转等操作,查看3d模型
  • TrackballControls 使用需要快速交互和动态旋转的场景,相机的移动相对平滑

也可以把两个控制器组合在一起使用,比如说:

  • 平移、缩放使用 OrbitControls
  • 旋转使用 TrackballControls

首先需要创建两个控制器:

1
2
3
4
5
6
7
8
9
10
const orbitControls = new OrbitControls(camera,renderer.domElement)
orbitControls.enableDamping = true
orbitControls.dampingFactor = 0.12
orbitControls.enableZoom = false

const trackBallControls = new TrackballControls(camera, renderer.domElement)
trackBallControls.noRotate = true
trackBallControls.noPan = true
trackBallControls.noZoom = false
trackBallControls.zoomSpeed = 1.5

在loop函数内需要更新控制器:

1
2
3
4
const target = orbitControls.target
orbitControls.update()
trackBallControls.target.set(target.x, target.y, target.z)
trackBallControls.update()

Cursor Following Camera Animation 相机跟随鼠标滑动

要做出相机运镜的效果,
需要对相机进行如下一系列处理:

  • 根据鼠标相对屏幕的位置计算相机位置
    • 计算每次鼠标相对屏幕移动的距离
    • 缩小移动步长,能够提高移动的平滑程度
  • 相机始终望向焦点物体 lookAt

相机坐标delta值的计算:

1
2
3
4
5
6
7
8
9
let mouseX = 0;
let mouseY = 0

window.onmousemove = e=>{
const windowHalfX = window.innerWidth / 2;
const windowHalfY = window.innerHeight / 2;
mouseX = (e.clientX - windowHalfX) / 100;
mouseY = (e.clientY - windowHalfY) / 100;
}

移动时缩小步长,保持相机lookAt焦点物体的位置:

1
2
3
4
5
6
7
8
function animate() {
// ...
camera.position.x += (mouseX - camera.position.x) * 0.05;
camera.position.y += (-mouseY - camera.position.y) * 0.05;
camera.lookAt(scene.position)
renderer.render(scene, camera);
}