qa-prevention-wlaq-vue/static/bi/tree/js/OrbitControls.js

540 lines
13 KiB
JavaScript
Raw Normal View History

2024-11-19 14:13:47 +08:00
/**
* @author qiao / https://github.com/qiao
* @author mrdoob / http://mrdoob.com
* @author alteredq / http://alteredqualia.com/
* @author WestLangley / http://github.com/WestLangley
* @modified wolfwind
*/
THREE.OrbitControls = function ( object, domElement ) {
this.object = object;
this.domElement = ( domElement !== undefined ) ? domElement : document;
// API
this.enabled = true;
this.center = new THREE.Vector3();
this.userZoom = true;
this.userZoomSpeed = 0.5;
this.userRotate = true;
this.userRotateSpeed = 1.0;
this.userPan = true;
this.userPanSpeed = 1.5;
this.autoRotate = false;
this.autoRotateSpeed = 2.0; // 30 seconds per round when fps is 60
this.minPolarAngle = 0; // radians
this.maxPolarAngle = Math.PI/2; // radians
this.minDistance = 0;
this.maxDistance = Infinity;
// 65 /*A*/, 83 /*S*/, 68 /*D*/
this.keys = { LEFT: 37, UP: 38, RIGHT: 39, BOTTOM: 40, ROTATE: 65, ZOOM: 83, PAN: 68 };
this.viewChanged = true;
// internals
var scope = this;
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 panStart = new THREE.Vector2();
var panEnd = new THREE.Vector2();
var panDelta = new THREE.Vector2();
var phiDelta = 0;
var thetaDelta = 0;
var scale = 1;
var lastPosition = new THREE.Vector3();
var STATE = { NONE: -1, ROTATE: 0, ZOOM: 1, PAN: 2, TOUCH_ROTATE: 3, TOUCH_ZOOM_PAN: 4 };
var state = STATE.NONE;
// events
var changeEvent = { type: 'change' };
var startEvent = { type: 'start'};
var endEvent = { type: 'end'};
this.reset = function (){
rotateStart = new THREE.Vector2();
rotateEnd = new THREE.Vector2();
rotateDelta = new THREE.Vector2();
zoomStart = new THREE.Vector2();
zoomEnd = new THREE.Vector2();
zoomDelta = new THREE.Vector2();
panStart = new THREE.Vector2();
panEnd = new THREE.Vector2();
panDelta = new THREE.Vector2();
phiDelta = 0;
thetaDelta = 0;
scale = 1;
lastPosition = new THREE.Vector3();
state = STATE.NONE;
this.center = new THREE.Vector3();
}
this.rotateLeft = function ( angle ) {
if ( angle === undefined ) {
angle = getAutoRotationAngle();
}
thetaDelta -= angle;
};
this.rotateRight = function ( angle ) {
if ( angle === undefined ) {
angle = getAutoRotationAngle();
}
thetaDelta += angle;
};
this.rotateUp = function ( angle ) {
if ( angle === undefined ) {
angle = getAutoRotationAngle();
}
phiDelta -= angle;
};
this.rotateDown = function ( angle ) {
if ( angle === undefined ) {
angle = getAutoRotationAngle();
}
phiDelta += angle;
};
this.zoomIn = function ( zoomScale ) {
if ( zoomScale === undefined ) {
zoomScale = getZoomScale();
}
scale /= zoomScale;
};
this.zoomOut = function ( zoomScale ) {
if ( zoomScale === undefined ) {
zoomScale = getZoomScale();
}
scale *= zoomScale;
};
this.pan = function ( distance ) {
distance.transformDirection( this.object.matrix );
distance.multiplyScalar( scope.userPanSpeed );
this.object.position.add( distance );
this.center.add( distance );
};
this.update = function () {
var position = this.object.position;
var offset = position.clone().sub( this.center );
// angle from z-axis around y-axis
var theta = Math.atan2( offset.x, offset.z );
// angle from y-axis
var phi = Math.atan2( Math.sqrt( offset.x * offset.x + offset.z * offset.z ), offset.y );
if ( this.autoRotate ) {
this.rotateLeft( getAutoRotationAngle() );
}
theta += thetaDelta;
phi += phiDelta;
// restrict phi to be between desired limits
phi = Math.max( this.minPolarAngle, Math.min( this.maxPolarAngle, phi ) );
// restrict phi to be betwee EPS and PI-EPS
phi = Math.max( EPS, Math.min( Math.PI - EPS, phi ) );
var radius = offset.length() * scale;
// restrict radius to be between desired limits
radius = Math.max( this.minDistance, Math.min( this.maxDistance, radius ) );
offset.x = radius * Math.sin( phi ) * Math.sin( theta );
offset.y = radius * Math.cos( phi );
offset.z = radius * Math.sin( phi ) * Math.cos( theta );
position.copy( this.center ).add( offset );
this.object.lookAt( this.center );
thetaDelta = 0;
phiDelta = 0;
scale = 1;
if ( lastPosition.distanceTo( this.object.position ) > 0 ) {
this.dispatchEvent( changeEvent );
lastPosition.copy( this.object.position );
this.viewChanged = true;
}
};
function getAutoRotationAngle() {
return 2 * Math.PI / 60 / 60 * scope.autoRotateSpeed;
}
function getZoomScale() {
return Math.pow( 0.95, scope.userZoomSpeed );
}
function onMouseDown( event ) {
if ( scope.enabled === false ) return;
if ( scope.userRotate === false ) return;
event.preventDefault();
if ( state === STATE.NONE )
{
if ( event.button === 2 )
state = STATE.PAN;
if ( event.button === 1 )
state = STATE.ZOOM;
if ( event.button === 0 )
state = STATE.ROTATE;
}
if ( state === STATE.ROTATE ) {
//state = STATE.ROTATE;
rotateStart.set( event.clientX, event.clientY );
} else if ( state === STATE.ZOOM ) {
//state = STATE.ZOOM;
zoomStart.set( event.clientX, event.clientY );
} else if ( state === STATE.PAN ) {
//state = STATE.PAN;
panStart.set(event.clientX, event.clientY);
}
document.addEventListener( 'mousemove', onMouseMove, false );
document.addEventListener( 'mouseup', onMouseUp, false );
}
function onMouseMove( event ) {
if ( scope.enabled === false ) return;
event.preventDefault();
if ( state === 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 === STATE.ZOOM ) {
zoomEnd.set( event.clientX, event.clientY );
zoomDelta.subVectors( zoomEnd, zoomStart );
if ( zoomDelta.y > 0 ) {
scope.zoomIn();
} else {
scope.zoomOut();
}
zoomStart.copy( zoomEnd );
} else if ( state === STATE.PAN ) {
panEnd.set(event.clientX, event.clientY);
panDelta.subVectors(panEnd, panStart);
scope.pan( new THREE.Vector3( - panDelta.x, panDelta.y , 0 ) );
panStart.copy(panEnd);
}
}
function onMouseUp( event ) {
if ( scope.enabled === false ) return;
if ( scope.userRotate === false ) return;
document.removeEventListener( 'mousemove', onMouseMove, false );
document.removeEventListener( 'mouseup', onMouseUp, false );
state = STATE.NONE;
}
function onMouseWheel( event ) {
if ( scope.enabled === false ) return;
if ( scope.userZoom === false ) return;
var delta = 0;
if ( event.wheelDelta ) { // WebKit / Opera / Explorer 9
delta = event.wheelDelta;
} else if ( event.detail ) { // Firefox
delta = - event.detail;
}
if ( delta > 0 ) {
scope.zoomOut();
} else {
scope.zoomIn();
}
}
function onKeyDown( event ) {
if ( scope.enabled === false ) return;
if ( scope.userPan === false ) return;
switch ( event.keyCode ) {
/*case scope.keys.UP:
scope.pan( new THREE.Vector3( 0, 1, 0 ) );
break;
case scope.keys.BOTTOM:
scope.pan( new THREE.Vector3( 0, - 1, 0 ) );
break;
case scope.keys.LEFT:
scope.pan( new THREE.Vector3( - 1, 0, 0 ) );
break;
case scope.keys.RIGHT:
scope.pan( new THREE.Vector3( 1, 0, 0 ) );
break;
*/
case scope.keys.ROTATE:
state = STATE.ROTATE;
break;
case scope.keys.ZOOM:
state = STATE.ZOOM;
break;
case scope.keys.PAN:
state = STATE.PAN;
break;
}
}
function onKeyUp( event ) {
switch ( event.keyCode ) {
case scope.keys.ROTATE:
case scope.keys.ZOOM:
case scope.keys.PAN:
state = STATE.NONE;
break;
}
}
function touchstart( event ) {
if ( scope.enabled === false ) return;
switch ( event.touches.length ) {
case 2:
state = STATE.TOUCH_ROTATE;
rotateStart.copy(event.touches[ 0 ].clientX, event.touches[ 0 ].clientY );
rotateEnd.copy(rotateStart);
break;
case 1:
state = STATE.TOUCH_ZOOM_PAN;
// var dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX;
// var dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY;
// _touchZoomDistanceEnd = _touchZoomDistanceStart = Math.sqrt( dx * dx + dy * dy );
// var x = ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX ) / 2;
// var y = ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY ) / 2;
panStart.set( event.touches[ 0 ].clientX, event.touches[ 0 ].clientY );
//panEnd.copy( panStart );
break;
default:
state = STATE.NONE;
}
document.addEventListener( 'touchend', touchend, false );
document.addEventListener( 'touchmove', touchmove, false );
scope.dispatchEvent( startEvent );
}
function touchmove( event ) {
if ( scope.enabled === false ) return;
event.preventDefault();
event.stopPropagation();
switch ( event.touches.length ) {
case 2:
rotateEnd.copy(event.touches[ 0 ].clientX, event.touches[ 0 ].clientY );
break;
case 1:
// var dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX;
// var dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY;
// _touchZoomDistanceEnd = Math.sqrt( dx * dx + dy * dy );
//
// var x = ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX ) / 2;
// var y = ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY ) / 2;
panEnd.set( event.touches[ 0 ].clientX, event.touches[ 0 ].clientY );
panDelta.subVectors(panEnd, panStart);
scope.pan(new THREE.Vector3( - panDelta.x, panDelta.y , 0 ));
panStart.copy(panEnd);
break;
default:
state = STATE.NONE;
}
}
function touchend( event ) {
if ( scope.enabled === false ) return;
// switch ( event.touches.length ) {
//
// case 2:
// if(scope.is3d) {
// rotateEnd.copy(event.touches[ 0 ].clientX, event.touches[ 0 ].clientY );
// rotateStart.copy(rotateEnd);
// }
// break;
// case 1:
//// _touchZoomDistanceStart = _touchZoomDistanceEnd = 0;
////
//// var x = ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX ) / 2;
//// var y = ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY ) / 2;
//// panEnd.copy( event.touches[ 0 ].clientX, event.touches[ 0 ].clientY );
//// panStart.copy( panEnd );
// break;
//
// }
document.removeEventListener('touchend', touchend, false);
document.removeEventListener('touchmove', touchmove, false);
state = STATE.NONE;
scope.dispatchEvent( endEvent );
}
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 ); // firefox
this.domElement.addEventListener( 'touchstart', touchstart, false );
window.addEventListener( 'keydown', onKeyDown, false );
window.addEventListener( 'keyup', onKeyUp, false );
};
THREE.OrbitControls.prototype = Object.create( THREE.EventDispatcher.prototype );