手写一个简单的 OrbitControls 轨道控制器
相信使用过THREE.JS的同学,都知道 OrbitControls 这个的轨道控制器,他是绕着一个观察点,来进行什么什么的… 反正就是那么个意思。
所以很明显OrbitControls的运动轨迹是一个球体,他是绕着球体进行运动的。
所以也很明显,我们只有知道每一点,球体的坐标 (x, y, z) 就可以实现这个效果,然后再把这个坐标,赋值给 相机对象就可以实现了
2.那么我们应该怎么获取到球体的坐标呢
这是我画的可视化图解,我们可以发现,球上的一点 P(x, y, z) 与 它的角度的之间的关系。
最后得出
x = R * Math.sin(theat) * Math.cos(phi);
y = R * Math.cos(theat);
z = R * Math.sin(theat) * Math.sin(phi);
所以这就是前面的理论部分,接下来我们就要完成具体的编码
class OrbitiControls {
constructor(camera, domElement) {
this.camera = camera;
this.domElement = domElement;
// 创建一个鼠标位置对象
this.mouse = {
x: 0,
y: 0,
down: false
}
// 绕着的目标
this.target = new Vector3(0,0,0);
// 计算轨道球体半径
this.radius = this.camera.position.distanceTo(this.target);
// 记录旋转的角度
this.rotate = {
theta: Math.atan2(this.camera.position.x, this.camera.position.z),
phi: Math.acos(this.camera.position.y / this.radius)
}
this.domElement.addEventListener('mousedown', this.onMouseDown.bind(this));
this.domElement.addEventListener('mouseup', this.onMouseUp.bind(this));
this.domElement.addEventListener('mousemove', this.onMouseMove.bind(this));
}
onMouseDown() {
// 当鼠标按下时
this.mouse.down = true;
}
onMouseUp() {
// 当鼠标抬起时
this.mouse.down = false;
}
onMouseMove(event) {
if (this.mouse.down) {
let x = event.movementX;
let y = event.movementY;
if (x > 3) x = 3;
if (x < -3) x = -3;
if (y > 3) y = 3;
if (y < -3) y = -3;
this.rotate.theta -= x * 0.01;
this.rotate.phi -= y * 0.01;
// 限制phi的范围
if (this.rotate.phi < 0.1) {
this.rotate.phi = 0.1;
}
if (this.rotate.phi > Math.PI - 0.1) {
this.rotate.phi = Math.PI - 0.1;
}
// 根据角度计算相机位置
this.camera.position.x =
this.radius * Math.sin(this.rotate.phi) * Math.cos(this.rotate.theta);
this.camera.position.y = this.radius * Math.cos(this.rotate.phi);
this.camera.position.z =
this.radius * Math.sin(this.rotate.phi) * Math.sin(this.rotate.theta);
this.camera.lookAt(this.target);
console.log(this.camera);
}
}
}