1 // This set of controls performs orbiting, dollying (zooming), and panning.
2 // Unlike TrackballControls, it maintains the "up" direction object.up (+Y by default).
4 // Orbit - left mouse / touch: one-finger move
5 // Zoom - middle mouse, or mousewheel / touch: two-finger spread or squish
6 // Pan - right mouse, or left mouse + ctrl/meta/shiftKey, or arrow keys / touch: two-finger move
8 THREE.OrbitControls = function ( object, domElement ) {
10 if ( domElement === undefined ) console.warn( 'THREE.OrbitControls: The second parameter "domElement" is now mandatory.' );
11 if ( domElement === document ) console.error( 'THREE.OrbitControls: "document" should not be used as the target "domElement". Please use "renderer.domElement" instead.' );
14 this.domElement = domElement;
16 // Set to false to disable this control
19 // "target" sets the location of focus, where the object orbits around
20 this.target = new THREE.Vector3();
22 // How far you can dolly in and out ( PerspectiveCamera only )
24 this.maxDistance = Infinity;
26 // How far you can zoom in and out ( OrthographicCamera only )
28 this.maxZoom = Infinity;
30 // How far you can orbit vertically, upper and lower limits.
31 // Range is 0 to Math.PI radians.
32 this.minPolarAngle = 0; // radians
33 this.maxPolarAngle = Math.PI; // radians
35 // How far you can orbit horizontally, upper and lower limits.
36 // If set, the interval [ min, max ] must be a sub-interval of [ - 2 PI, 2 PI ], with ( max - min < 2 PI )
37 this.minAzimuthAngle = - Infinity; // radians
38 this.maxAzimuthAngle = Infinity; // radians
40 // Set to true to enable damping (inertia)
41 // If damping is enabled, you must call controls.update() in your animation loop
42 this.enableDamping = false;
43 this.dampingFactor = 0.05;
45 // This option actually enables dollying in and out; left as "zoom" for backwards compatibility.
46 // Set to false to disable zooming
47 this.enableZoom = true;
50 // Set to false to disable rotating
51 this.enableRotate = true;
52 this.rotateSpeed = 1.0;
54 // Set to false to disable panning
55 this.enablePan = true;
57 this.screenSpacePanning = true; // if false, pan orthogonal to world-space direction camera.up
58 this.keyPanSpeed = 7.0; // pixels moved per arrow key push
60 // Set to true to automatically rotate around the target
61 // If auto-rotate is enabled, you must call controls.update() in your animation loop
62 this.autoRotate = false;
63 this.autoRotateSpeed = 2.0; // 30 seconds per orbit when fps is 60
65 // The four arrow keys
66 this.keys = { LEFT: 37, UP: 38, RIGHT: 39, BOTTOM: 40 };
69 this.mouseButtons = { LEFT: THREE.MOUSE.ROTATE, MIDDLE: THREE.MOUSE.DOLLY, RIGHT: THREE.MOUSE.PAN };
72 this.touches = { ONE: THREE.TOUCH.ROTATE, TWO: THREE.TOUCH.DOLLY_PAN };
75 this.target0 = this.target.clone();
76 this.position0 = this.object.position.clone();
77 this.zoom0 = this.object.zoom;
79 // the target DOM element for key events
80 this._domElementKeyEvents = null;
86 this.getPolarAngle = function () {
92 this.getAzimuthalAngle = function () {
94 return spherical.theta;
98 this.listenToKeyEvents = function ( domElement ) {
100 domElement.addEventListener( 'keydown', onKeyDown );
101 this._domElementKeyEvents = domElement;
105 this.saveState = function () {
107 scope.target0.copy( scope.target );
108 scope.position0.copy( scope.object.position );
109 scope.zoom0 = scope.object.zoom;
113 this.reset = function () {
115 scope.target.copy( scope.target0 );
116 scope.object.position.copy( scope.position0 );
117 scope.object.zoom = scope.zoom0;
119 scope.object.updateProjectionMatrix();
120 scope.dispatchEvent( changeEvent );
128 // this method is exposed, but perhaps it would be better if we can make it private...
129 this.update = function () {
131 var offset = new THREE.Vector3();
133 // so camera.up is the orbit axis
134 var quat = new THREE.Quaternion().setFromUnitVectors( object.up, new THREE.Vector3( 0, 1, 0 ) );
135 var quatInverse = quat.clone().invert();
137 var lastPosition = new THREE.Vector3();
138 var lastQuaternion = new THREE.Quaternion();
140 var twoPI = 2 * Math.PI;
142 return function update() {
144 var position = scope.object.position;
146 offset.copy( position ).sub( scope.target );
148 // rotate offset to "y-axis-is-up" space
149 offset.applyQuaternion( quat );
151 // angle from z-axis around y-axis
152 spherical.setFromVector3( offset );
154 if ( scope.autoRotate && state === STATE.NONE ) {
156 rotateLeft( getAutoRotationAngle() );
160 if ( scope.enableDamping ) {
162 spherical.theta += sphericalDelta.theta * scope.dampingFactor;
163 spherical.phi += sphericalDelta.phi * scope.dampingFactor;
167 spherical.theta += sphericalDelta.theta;
168 spherical.phi += sphericalDelta.phi;
172 // restrict theta to be between desired limits
174 var min = scope.minAzimuthAngle;
175 var max = scope.maxAzimuthAngle;
177 if ( isFinite( min ) && isFinite( max ) ) {
179 if ( min < - Math.PI ) min += twoPI; else if ( min > Math.PI ) min -= twoPI;
181 if ( max < - Math.PI ) max += twoPI; else if ( max > Math.PI ) max -= twoPI;
185 spherical.theta = Math.max( min, Math.min( max, spherical.theta ) );
189 spherical.theta = ( spherical.theta > ( min + max ) / 2 ) ?
190 Math.max( min, spherical.theta ) :
191 Math.min( max, spherical.theta );
197 // restrict phi to be between desired limits
198 spherical.phi = Math.max( scope.minPolarAngle, Math.min( scope.maxPolarAngle, spherical.phi ) );
200 spherical.makeSafe();
203 spherical.radius *= scale;
205 // restrict radius to be between desired limits
206 spherical.radius = Math.max( scope.minDistance, Math.min( scope.maxDistance, spherical.radius ) );
208 // move target to panned location
210 if ( scope.enableDamping === true ) {
212 scope.target.addScaledVector( panOffset, scope.dampingFactor );
216 scope.target.add( panOffset );
220 offset.setFromSpherical( spherical );
222 // rotate offset back to "camera-up-vector-is-up" space
223 offset.applyQuaternion( quatInverse );
225 position.copy( scope.target ).add( offset );
227 scope.object.lookAt( scope.target );
229 if ( scope.enableDamping === true ) {
231 sphericalDelta.theta *= ( 1 - scope.dampingFactor );
232 sphericalDelta.phi *= ( 1 - scope.dampingFactor );
234 panOffset.multiplyScalar( 1 - scope.dampingFactor );
238 sphericalDelta.set( 0, 0, 0 );
240 panOffset.set( 0, 0, 0 );
246 // update condition is:
247 // min(camera displacement, camera rotation in radians)^2 > EPS
248 // using small-angle approximation cos(x/2) = 1 - x^2 / 8
251 lastPosition.distanceToSquared( scope.object.position ) > EPS ||
252 8 * ( 1 - lastQuaternion.dot( scope.object.quaternion ) ) > EPS ) {
254 scope.dispatchEvent( changeEvent );
256 lastPosition.copy( scope.object.position );
257 lastQuaternion.copy( scope.object.quaternion );
270 this.dispose = function () {
272 scope.domElement.removeEventListener( 'contextmenu', onContextMenu );
274 scope.domElement.removeEventListener( 'pointerdown', onPointerDown );
275 scope.domElement.removeEventListener( 'wheel', onMouseWheel );
277 scope.domElement.removeEventListener( 'touchstart', onTouchStart );
278 scope.domElement.removeEventListener( 'touchend', onTouchEnd );
279 scope.domElement.removeEventListener( 'touchmove', onTouchMove );
281 scope.domElement.ownerDocument.removeEventListener( 'pointermove', onPointerMove );
282 scope.domElement.ownerDocument.removeEventListener( 'pointerup', onPointerUp );
285 if ( scope._domElementKeyEvents !== null ) {
287 scope._domElementKeyEvents.removeEventListener( 'keydown', onKeyDown );
291 //scope.dispatchEvent( { type: 'dispose' } ); // should this be added here?
301 var changeEvent = { type: 'change' };
302 var startEvent = { type: 'start' };
303 var endEvent = { type: 'end' };
313 TOUCH_DOLLY_ROTATE: 6
316 var state = STATE.NONE;
320 // current position in spherical coordinates
321 var spherical = new THREE.Spherical();
322 var sphericalDelta = new THREE.Spherical();
325 var panOffset = new THREE.Vector3();
326 var zoomChanged = false;
328 var rotateStart = new THREE.Vector2();
329 var rotateEnd = new THREE.Vector2();
330 var rotateDelta = new THREE.Vector2();
332 var panStart = new THREE.Vector2();
333 var panEnd = new THREE.Vector2();
334 var panDelta = new THREE.Vector2();
336 var dollyStart = new THREE.Vector2();
337 var dollyEnd = new THREE.Vector2();
338 var dollyDelta = new THREE.Vector2();
340 function getAutoRotationAngle() {
342 return 2 * Math.PI / 60 / 60 * scope.autoRotateSpeed;
346 function getZoomScale() {
348 return Math.pow( 0.95, scope.zoomSpeed );
352 function rotateLeft( angle ) {
354 sphericalDelta.theta -= angle;
358 function rotateUp( angle ) {
360 sphericalDelta.phi -= angle;
364 var panLeft = function () {
366 var v = new THREE.Vector3();
368 return function panLeft( distance, objectMatrix ) {
370 v.setFromMatrixColumn( objectMatrix, 0 ); // get X column of objectMatrix
371 v.multiplyScalar( - distance );
379 var panUp = function () {
381 var v = new THREE.Vector3();
383 return function panUp( distance, objectMatrix ) {
385 if ( scope.screenSpacePanning === true ) {
387 v.setFromMatrixColumn( objectMatrix, 1 );
391 v.setFromMatrixColumn( objectMatrix, 0 );
392 v.crossVectors( scope.object.up, v );
396 v.multiplyScalar( distance );
404 // deltaX and deltaY are in pixels; right and down are positive
405 var pan = function () {
407 var offset = new THREE.Vector3();
409 return function pan( deltaX, deltaY ) {
411 var element = scope.domElement;
413 if ( scope.object.isPerspectiveCamera ) {
416 var position = scope.object.position;
417 offset.copy( position ).sub( scope.target );
418 var targetDistance = offset.length();
420 // half of the fov is center to top of screen
421 targetDistance *= Math.tan( ( scope.object.fov / 2 ) * Math.PI / 180.0 );
423 // we use only clientHeight here so aspect ratio does not distort speed
424 panLeft( 2 * deltaX * targetDistance / element.clientHeight, scope.object.matrix );
425 panUp( 2 * deltaY * targetDistance / element.clientHeight, scope.object.matrix );
427 } else if ( scope.object.isOrthographicCamera ) {
430 panLeft( deltaX * ( scope.object.right - scope.object.left ) / scope.object.zoom / element.clientWidth, scope.object.matrix );
431 panUp( deltaY * ( scope.object.top - scope.object.bottom ) / scope.object.zoom / element.clientHeight, scope.object.matrix );
435 // camera neither orthographic nor perspective
436 console.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - pan disabled.' );
437 scope.enablePan = false;
445 function dollyOut( dollyScale ) {
447 if ( scope.object.isPerspectiveCamera ) {
451 } else if ( scope.object.isOrthographicCamera ) {
453 scope.object.zoom = Math.max( scope.minZoom, Math.min( scope.maxZoom, scope.object.zoom * dollyScale ) );
454 scope.object.updateProjectionMatrix();
459 console.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.' );
460 scope.enableZoom = false;
466 function dollyIn( dollyScale ) {
468 if ( scope.object.isPerspectiveCamera ) {
472 } else if ( scope.object.isOrthographicCamera ) {
474 scope.object.zoom = Math.max( scope.minZoom, Math.min( scope.maxZoom, scope.object.zoom / dollyScale ) );
475 scope.object.updateProjectionMatrix();
480 console.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.' );
481 scope.enableZoom = false;
488 // event callbacks - update the object state
491 function handleMouseDownRotate( event ) {
493 rotateStart.set( event.clientX, event.clientY );
497 function handleMouseDownDolly( event ) {
499 dollyStart.set( event.clientX, event.clientY );
503 function handleMouseDownPan( event ) {
505 panStart.set( event.clientX, event.clientY );
509 function handleMouseMoveRotate( event ) {
511 rotateEnd.set( event.clientX, event.clientY );
513 rotateDelta.subVectors( rotateEnd, rotateStart ).multiplyScalar( scope.rotateSpeed );
515 var element = scope.domElement;
517 rotateLeft( 2 * Math.PI * rotateDelta.x / element.clientHeight ); // yes, height
519 rotateUp( 2 * Math.PI * rotateDelta.y / element.clientHeight );
521 rotateStart.copy( rotateEnd );
527 function handleMouseMoveDolly( event ) {
529 dollyEnd.set( event.clientX, event.clientY );
531 dollyDelta.subVectors( dollyEnd, dollyStart );
533 if ( dollyDelta.y > 0 ) {
535 dollyOut( getZoomScale() );
537 } else if ( dollyDelta.y < 0 ) {
539 dollyIn( getZoomScale() );
543 dollyStart.copy( dollyEnd );
549 function handleMouseMovePan( event ) {
551 panEnd.set( event.clientX, event.clientY );
553 panDelta.subVectors( panEnd, panStart ).multiplyScalar( scope.panSpeed );
555 pan( panDelta.x, panDelta.y );
557 panStart.copy( panEnd );
563 function handleMouseUp( /*event*/ ) {
569 function handleMouseWheel( event ) {
571 if ( event.deltaY < 0 ) {
573 dollyIn( getZoomScale() );
575 } else if ( event.deltaY > 0 ) {
577 dollyOut( getZoomScale() );
585 function handleKeyDown( event ) {
587 var needsUpdate = false;
589 switch ( event.keyCode ) {
592 pan( 0, scope.keyPanSpeed );
596 case scope.keys.BOTTOM:
597 pan( 0, - scope.keyPanSpeed );
601 case scope.keys.LEFT:
602 pan( scope.keyPanSpeed, 0 );
606 case scope.keys.RIGHT:
607 pan( - scope.keyPanSpeed, 0 );
615 // prevent the browser from scrolling on cursor keys
616 event.preventDefault();
625 function handleTouchStartRotate( event ) {
627 if ( event.touches.length == 1 ) {
629 rotateStart.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY );
633 var x = 0.5 * ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX );
634 var y = 0.5 * ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY );
636 rotateStart.set( x, y );
642 function handleTouchStartPan( event ) {
644 if ( event.touches.length == 1 ) {
646 panStart.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY );
650 var x = 0.5 * ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX );
651 var y = 0.5 * ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY );
653 panStart.set( x, y );
659 function handleTouchStartDolly( event ) {
661 var dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX;
662 var dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY;
664 var distance = Math.sqrt( dx * dx + dy * dy );
666 dollyStart.set( 0, distance );
670 function handleTouchStartDollyPan( event ) {
672 if ( scope.enableZoom ) handleTouchStartDolly( event );
674 if ( scope.enablePan ) handleTouchStartPan( event );
678 function handleTouchStartDollyRotate( event ) {
680 if ( scope.enableZoom ) handleTouchStartDolly( event );
682 if ( scope.enableRotate ) handleTouchStartRotate( event );
686 function handleTouchMoveRotate( event ) {
688 if ( event.touches.length == 1 ) {
690 rotateEnd.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY );
694 var x = 0.5 * ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX );
695 var y = 0.5 * ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY );
697 rotateEnd.set( x, y );
701 rotateDelta.subVectors( rotateEnd, rotateStart ).multiplyScalar( scope.rotateSpeed );
703 var element = scope.domElement;
705 rotateLeft( 2 * Math.PI * rotateDelta.x / element.clientHeight ); // yes, height
707 rotateUp( 2 * Math.PI * rotateDelta.y / element.clientHeight );
709 rotateStart.copy( rotateEnd );
713 function handleTouchMovePan( event ) {
715 if ( event.touches.length == 1 ) {
717 panEnd.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY );
721 var x = 0.5 * ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX );
722 var y = 0.5 * ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY );
728 panDelta.subVectors( panEnd, panStart ).multiplyScalar( scope.panSpeed );
730 pan( panDelta.x, panDelta.y );
732 panStart.copy( panEnd );
736 function handleTouchMoveDolly( event ) {
738 var dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX;
739 var dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY;
741 var distance = Math.sqrt( dx * dx + dy * dy );
743 dollyEnd.set( 0, distance );
745 dollyDelta.set( 0, Math.pow( dollyEnd.y / dollyStart.y, scope.zoomSpeed ) );
747 dollyOut( dollyDelta.y );
749 dollyStart.copy( dollyEnd );
753 function handleTouchMoveDollyPan( event ) {
755 if ( scope.enableZoom ) handleTouchMoveDolly( event );
757 if ( scope.enablePan ) handleTouchMovePan( event );
761 function handleTouchMoveDollyRotate( event ) {
763 if ( scope.enableZoom ) handleTouchMoveDolly( event );
765 if ( scope.enableRotate ) handleTouchMoveRotate( event );
769 function handleTouchEnd( /*event*/ ) {
776 // event handlers - FSM: listen for events and reset state
779 function onPointerDown( event ) {
781 if ( scope.enabled === false ) return;
783 switch ( event.pointerType ) {
787 onMouseDown( event );
796 function onPointerMove( event ) {
798 if ( scope.enabled === false ) return;
800 switch ( event.pointerType ) {
804 onMouseMove( event );
813 function onPointerUp( event ) {
815 switch ( event.pointerType ) {
828 function onMouseDown( event ) {
830 // Prevent the browser from scrolling.
831 event.preventDefault();
833 // Manually set the focus since calling preventDefault above
834 // prevents the browser from setting it automatically.
836 scope.domElement.focus ? scope.domElement.focus() : window.focus();
840 switch ( event.button ) {
844 mouseAction = scope.mouseButtons.LEFT;
849 mouseAction = scope.mouseButtons.MIDDLE;
854 mouseAction = scope.mouseButtons.RIGHT;
863 switch ( mouseAction ) {
865 case THREE.MOUSE.DOLLY:
867 if ( scope.enableZoom === false ) return;
869 handleMouseDownDolly( event );
875 case THREE.MOUSE.ROTATE:
877 if ( event.ctrlKey || event.metaKey || event.shiftKey ) {
879 if ( scope.enablePan === false ) return;
881 handleMouseDownPan( event );
887 if ( scope.enableRotate === false ) return;
889 handleMouseDownRotate( event );
891 state = STATE.ROTATE;
897 case THREE.MOUSE.PAN:
899 if ( event.ctrlKey || event.metaKey || event.shiftKey ) {
901 if ( scope.enableRotate === false ) return;
903 handleMouseDownRotate( event );
905 state = STATE.ROTATE;
909 if ( scope.enablePan === false ) return;
911 handleMouseDownPan( event );
925 if ( state !== STATE.NONE ) {
927 scope.domElement.ownerDocument.addEventListener( 'pointermove', onPointerMove );
928 scope.domElement.ownerDocument.addEventListener( 'pointerup', onPointerUp );
930 scope.dispatchEvent( startEvent );
936 function onMouseMove( event ) {
938 if ( scope.enabled === false ) return;
940 event.preventDefault();
946 if ( scope.enableRotate === false ) return;
948 handleMouseMoveRotate( event );
954 if ( scope.enableZoom === false ) return;
956 handleMouseMoveDolly( event );
962 if ( scope.enablePan === false ) return;
964 handleMouseMovePan( event );
972 function onMouseUp( event ) {
974 scope.domElement.ownerDocument.removeEventListener( 'pointermove', onPointerMove );
975 scope.domElement.ownerDocument.removeEventListener( 'pointerup', onPointerUp );
977 if ( scope.enabled === false ) return;
979 handleMouseUp( event );
981 scope.dispatchEvent( endEvent );
987 function onMouseWheel( event ) {
989 if ( scope.enabled === false || scope.enableZoom === false || ( state !== STATE.NONE && state !== STATE.ROTATE ) ) return;
991 event.preventDefault();
992 event.stopPropagation();
994 scope.dispatchEvent( startEvent );
996 handleMouseWheel( event );
998 scope.dispatchEvent( endEvent );
1002 function onKeyDown( event ) {
1004 if ( scope.enabled === false || scope.enablePan === false ) return;
1006 handleKeyDown( event );
1010 function onTouchStart( event ) {
1012 if ( scope.enabled === false ) return;
1014 event.preventDefault(); // prevent scrolling
1016 switch ( event.touches.length ) {
1020 switch ( scope.touches.ONE ) {
1022 case THREE.TOUCH.ROTATE:
1024 if ( scope.enableRotate === false ) return;
1026 handleTouchStartRotate( event );
1028 state = STATE.TOUCH_ROTATE;
1032 case THREE.TOUCH.PAN:
1034 if ( scope.enablePan === false ) return;
1036 handleTouchStartPan( event );
1038 state = STATE.TOUCH_PAN;
1052 switch ( scope.touches.TWO ) {
1054 case THREE.TOUCH.DOLLY_PAN:
1056 if ( scope.enableZoom === false && scope.enablePan === false ) return;
1058 handleTouchStartDollyPan( event );
1060 state = STATE.TOUCH_DOLLY_PAN;
1064 case THREE.TOUCH.DOLLY_ROTATE:
1066 if ( scope.enableZoom === false && scope.enableRotate === false ) return;
1068 handleTouchStartDollyRotate( event );
1070 state = STATE.TOUCH_DOLLY_ROTATE;
1088 if ( state !== STATE.NONE ) {
1090 scope.dispatchEvent( startEvent );
1096 function onTouchMove( event ) {
1098 if ( scope.enabled === false ) return;
1100 event.preventDefault(); // prevent scrolling
1101 event.stopPropagation();
1105 case STATE.TOUCH_ROTATE:
1107 if ( scope.enableRotate === false ) return;
1109 handleTouchMoveRotate( event );
1115 case STATE.TOUCH_PAN:
1117 if ( scope.enablePan === false ) return;
1119 handleTouchMovePan( event );
1125 case STATE.TOUCH_DOLLY_PAN:
1127 if ( scope.enableZoom === false && scope.enablePan === false ) return;
1129 handleTouchMoveDollyPan( event );
1135 case STATE.TOUCH_DOLLY_ROTATE:
1137 if ( scope.enableZoom === false && scope.enableRotate === false ) return;
1139 handleTouchMoveDollyRotate( event );
1153 function onTouchEnd( event ) {
1155 if ( scope.enabled === false ) return;
1157 handleTouchEnd( event );
1159 scope.dispatchEvent( endEvent );
1165 function onContextMenu( event ) {
1167 if ( scope.enabled === false ) return;
1169 event.preventDefault();
1175 scope.domElement.addEventListener( 'contextmenu', onContextMenu );
1177 scope.domElement.addEventListener( 'pointerdown', onPointerDown );
1178 scope.domElement.addEventListener( 'wheel', onMouseWheel );
1180 scope.domElement.addEventListener( 'touchstart', onTouchStart );
1181 scope.domElement.addEventListener( 'touchend', onTouchEnd );
1182 scope.domElement.addEventListener( 'touchmove', onTouchMove );
1184 // force an update at start
1190 THREE.OrbitControls.prototype = Object.create( THREE.EventDispatcher.prototype );
1191 THREE.OrbitControls.prototype.constructor = THREE.OrbitControls;
1194 // This set of controls performs orbiting, dollying (zooming), and panning.
1195 // Unlike TrackballControls, it maintains the "up" direction object.up (+Y by default).
1196 // This is very similar to OrbitControls, another set of touch behavior
1198 // Orbit - right mouse, or left mouse + ctrl/meta/shiftKey / touch: two-finger rotate
1199 // Zoom - middle mouse, or mousewheel / touch: two-finger spread or squish
1200 // Pan - left mouse, or arrow keys / touch: one-finger move
1202 THREE.MapControls = function ( object, domElement ) {
1204 THREE.OrbitControls.call( this, object, domElement );
1206 this.screenSpacePanning = false; // pan orthogonal to world-space direction camera.up
1208 this.mouseButtons.LEFT = THREE.MOUSE.PAN;
1209 this.mouseButtons.RIGHT = THREE.MOUSE.ROTATE;
1211 this.touches.ONE = THREE.TOUCH.PAN;
1212 this.touches.TWO = THREE.TOUCH.DOLLY_ROTATE;
1216 THREE.MapControls.prototype = Object.create( THREE.EventDispatcher.prototype );
1217 THREE.MapControls.prototype.constructor = THREE.MapControls;