我正在使用 OrbitControls.js 来允许鼠标交互。我在场景中添加了一个按钮,允许将相机“重置”到任何鼠标交互之前的状态。
我试图在任何交互之前保存 camera.position 和 camera.rotation :
camera_initial_position = camera.position; camera_initial_rotation = camera.rotation;
按下“reset”按钮后,初始位置和旋转设置:
camera.position = camera_initial_position; camera.rotation = camera_initial_rotation;
如果不使用平底锅,它会很好地工作。如果用户使用鼠标右键平移,则上述代码无法“重置”相机。
将相机“重置”到之前状态的正确方法是什么?
three.js 的修订版是 r58,这是 OrbitControls.js:
/** * @作者乔/https://github.com/qiao * @author mrdoob / http://mrdoob.com * @author changedq / http://alteredqualia.com/ * @author WestLangley / http://github.com/WestLangley */ 三.OrbitControls = function (object, domElement) { this.object = 对象; this.domElement = (domElement!== undefined) ?domElement:文档; // API this.enabled = true; this.center = new THREE.Vector3(); this.userZoom = true; this.userZoomSpeed = 1.0; this.userRotate = true; this.userRotateSpeed = 1.0; this.userPan = true; this.userPanSpeed = 2.0; this.autoRotate = false; this.autoRotateSpeed = 2.0; // 当 fps 为 60 时,每轮 30 秒 this.minPolarAngle = 0; // 弧度 this.maxPolarAngle = Math.PI; // 弧度 this.minDistance = 0; this.maxDistance = 无穷大; this.keys = { 左:37,上:38,右:39,下:40 }; // 内部 变量范围=这个; var EPS = 0.000001; var PIXELS_PER_ROUND = 1800; var rotateStart = new THREE.Vector2(); var rotateEnd = new THREE.Vector2(); var rotateDelta = new THREE.Vector2(); var zoomStart = new THREE.Vector2(); var zoomEnd = new THREE.Vector2(); var zoomDelta = new THREE.Vector2(); var phiDelta = 0; var thetaDelta = 0; 变量比例 = 1; var lastPosition = new THREE.Vector3(); var状态={无:-1,旋转:0,缩放:1,平移:2}; 变种状态=状态。无; // 事件 var changeEvent = { type: 'change' }; this.rotateLeft = 函数(角度){ 如果(角度===未定义){ 角度 = getAutoRotationAngle(); } thetaDelta -= 角度; }; this.rotateRight = 函数(角度){ 如果(角度===未定义){ 角度 = getAutoRotationAngle(); } thetaDelta += 角度; }; this.rotateUp = 函数(角度){ 如果(角度===未定义){ 角度 = getAutoRotationAngle(); } phiDelta -= 角度; }; this.rotateDown = 函数(角度){ 如果(角度===未定义){ 角度 = getAutoRotationAngle(); } phiDelta += 角度; }; this.zoomIn = function (zoomScale) { 如果(缩放比例===未定义){ zoomScale = getZoomScale(); } 缩放 /= 缩放缩放; }; this.zoomOut = function (zoomScale) { 如果(缩放比例===未定义){ zoomScale = getZoomScale(); } 比例 *= 缩放比例; }; this.pan = 函数(距离){ distance.transformDirection(this.object.matrix); distance.multiplyScalar(scope.userPanSpeed); this.object.position.add(距离); this.center.add(距离); }; this.update = 函数 () { var 位置 = this.object.position; var offset = position.clone().sub(this.center); // z 轴绕 y 轴的角度 var theta = Math.atan2(offset.x, offset.z); // 与y轴的角度 var phi = Math.atan2( Math.sqrt( offset.x * offset.x + offset.z * offset.z ), offset.y ); 如果(this.autoRotate){ this.rotateLeft(getAutoRotationAngle()); } θ+=θDelta; phi += phiDelta; // 将 phi 限制在所需的限制之间 phi = Math.max(this.minPolarAngle, Math.min(this.maxPolarAngle, phi)); // 将 phi 限制在 EPS 和 PI-EPS 之间 phi = Math.max(EPS, Math.min(Math.PI - EPS, phi)); var radius = offset.length() * scale; // 将半径限制在所需范围之间 半径= Math.max(this.minDistance,Math.min(this.maxDistance,半径)); offset.x = 半径 * Math.sin( phi ) * Math.sin( theta ); offset.y = 半径 * Math.cos( phi ); offset.z = 半径 * Math.sin( phi ) * Math.cos( theta ); position.copy(this.center).add(offset); this.object.lookAt(this.center); θDelta = 0; phiDelta = 0; 规模 = 1; if ( lastPosition.distanceTo( this.object.position ) > 0 ) { this.dispatchEvent(changeEvent); lastPosition.copy(this.object.position); } }; 函数 getAutoRotationAngle() { 返回 2 * Math.PI / 60 / 60 * scope.autoRotateSpeed; } 函数 getZoomScale() { 返回 Math.pow(0.95, scope.userZoomSpeed); } 函数 onMouseDown(事件){ if (scope.enabled === false) 返回; if (scope.userRotate === false) 返回; event.preventDefault(); if ( event.button === 0 ) { 状态=状态。旋转; rotateStart.set(event.clientX, event.clientY); } else if ( event.button === 1 ) { 状态=状态。缩放; zoomStart.set(event.clientX, event.clientY); } else if ( event.button === 2 ) { 状态=状态.PAN; } document.addEventListener('mousemove', onMouseMove, false); document.addEventListener('mouseup', onMouseUp, false); } 功能 onMouseMove(事件){ if (scope.enabled === false) 返回; event.preventDefault(); if ( 状态 === STATE.ROTATE ) { rotateEnd.set(event.clientX, event.clientY); rotateDelta.subVectors(rotateEnd, rotateStart); scope.rotateLeft(2 * Math.PI * rotateDelta.x / PIXELS_PER_ROUND * scope.userRotateSpeed); scope.rotateUp(2 * Math.PI * rotateDelta.y / PIXELS_PER_ROUND * scope.userRotateSpeed); rotateStart.copy(rotateEnd); } else if ( 状态 === STATE.ZOOM ) { zoomEnd.set(event.clientX, event.clientY); zoomDelta.subVectors(zoomEnd, zoomStart); if (zoomDelta.y > 0) { scope.zoomIn(); } 别的 { scope.zoomOut(); } zoomStart.copy(zoomEnd); } else if ( 状态 === STATE.PAN ) { var moveX = event.movementX || 事件.mozMovementX || event.webkitMovementX || 0; var moveY = event.movementY || 事件.mozMovementY || event.webkitMovementY || 0; scope.pan(new THREE.Vector3(-motionX, moveY, 0)); } } 功能 onMouseUp(事件){ if (scope.enabled === false) 返回; if (scope.userRotate === false) 返回; document.removeEventListener('mousemove', onMouseMove, false); document.removeEventListener('mouseup', onMouseUp, false); 状态=状态。无; } 功能 onMouseWheel(事件){ if (scope.enabled === false) 返回; if (scope.userZoom === false) 返回; 变量增量 = 0; if ( event.wheelDelta ) { // WebKit / Opera / Explorer 9 delta = event.wheelDelta; } else if ( event.detail ) { // 火狐 delta = - event.detail; } 如果(增量> 0){ scope.zoomOut(); } 别的 { scope.zoomIn(); } } 函数 onKeyDown( 事件 ) { if (scope.enabled === false) 返回; if (scope.userPan === false) 返回; 开关(事件.keyCode){ 案例范围.keys.UP: scope.pan(new THREE.Vector3(0,1,0)); 休息; 案例范围.keys.BOTTOM: scope.pan(new THREE.Vector3(0, - 1, 0)); 休息; 案例范围.keys.LEFT: scope.pan(new THREE.Vector3(-1,0,0)); 休息; 案例范围.keys.RIGHT: scope.pan(new THREE.Vector3(1, 0, 0)); 休息; } } this.domElement.addEventListener('contextmenu', function (event) { event.preventDefault(); }, false); this.domElement.addEventListener('mousedown', onMouseDown, false); this.domElement.addEventListener('mousewheel', onMouseWheel, false); this.domElement.addEventListener('DOMMouseScroll', onMouseWheel, false); //火狐 this.domElement.addEventListener('keydown', onKeyDown, false); }; 三.OrbitControls.prototype = Object.create(三.EventDispatcher.prototype);