手写一个简单的 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);}}}