Explorar o código

TrackballControls: Fully migrate to pointer events. (#22006)

* TrackballControls: Filly migrate to pointer events.

* TrackballControls: Fix onTouchStart().
Michael Herzog %!s(int64=4) %!d(string=hai) anos
pai
achega
2c78502bc0
Modificáronse 2 ficheiros con 243 adicións e 126 borrados
  1. 121 62
      examples/js/controls/TrackballControls.js
  2. 122 64
      examples/jsm/controls/TrackballControls.js

+ 121 - 62
examples/js/controls/TrackballControls.js

@@ -27,7 +27,9 @@
 				TOUCH_ZOOM_PAN: 4
 			};
 			this.object = object;
-			this.domElement = domElement; // API
+			this.domElement = domElement;
+			this.domElement.style.touchAction = 'none'; // disable touch scroll
+			// API
 
 			this.enabled = true;
 			this.screen = {
@@ -76,7 +78,9 @@
 				_zoomStart = new THREE.Vector2(),
 				_zoomEnd = new THREE.Vector2(),
 				_panStart = new THREE.Vector2(),
-				_panEnd = new THREE.Vector2(); // for reset
+				_panEnd = new THREE.Vector2(),
+				_pointers = [],
+				_pointerPositions = {}; // for reset
 
 
 			this.target0 = this.target.clone();
@@ -383,13 +387,23 @@
 
 				if ( scope.enabled === false ) return;
 
-				switch ( event.pointerType ) {
+				if ( _pointers.length === 0 ) {
 
-					case 'mouse':
-					case 'pen':
-						onMouseDown( event );
-						break;
-        // TODO touch
+					scope.domElement.ownerDocument.addEventListener( 'pointermove', onPointerMove );
+					scope.domElement.ownerDocument.addEventListener( 'pointerup', onPointerUp );
+
+				} //
+
+
+				addPointer( event );
+
+				if ( event.pointerType === 'touch' ) {
+
+					onTouchStart( event );
+
+				} else {
+
+					onMouseDown( event );
 
 				}
 
@@ -399,13 +413,13 @@
 
 				if ( scope.enabled === false ) return;
 
-				switch ( event.pointerType ) {
+				if ( event.pointerType === 'touch' ) {
 
-					case 'mouse':
-					case 'pen':
-						onMouseMove( event );
-						break;
-        // TODO touch
+					onTouchMove( event );
+
+				} else {
+
+					onMouseMove( event );
 
 				}
 
@@ -415,18 +429,34 @@
 
 				if ( scope.enabled === false ) return;
 
-				switch ( event.pointerType ) {
+				if ( event.pointerType === 'touch' ) {
 
-					case 'mouse':
-					case 'pen':
-						onMouseUp();
-						break;
-        // TODO touch
+					onTouchEnd( event );
+
+				} else {
+
+					onMouseUp( event );
+
+				} //
+
+
+				removePointer( event );
+
+				if ( _pointers.length === 0 ) {
+
+					scope.domElement.ownerDocument.removeEventListener( 'pointermove', onPointerMove );
+					scope.domElement.ownerDocument.removeEventListener( 'pointerup', onPointerUp );
 
 				}
 
 			}
 
+			function onPointerCancel( event ) {
+
+				removePointer( event );
+
+			}
+
 			function keydown( event ) {
 
 				if ( scope.enabled === false ) return;
@@ -515,7 +545,6 @@
 
 			function onMouseMove( event ) {
 
-				if ( scope.enabled === false ) return;
 				const state = _keyState !== STATE.NONE ? _keyState : _state;
 
 				if ( state === STATE.ROTATE && ! scope.noRotate ) {
@@ -538,7 +567,6 @@
 
 			function onMouseUp() {
 
-				if ( scope.enabled === false ) return;
 				_state = STATE.NONE;
 				scope.domElement.ownerDocument.removeEventListener( 'pointermove', onPointerMove );
 				scope.domElement.ownerDocument.removeEventListener( 'pointerup', onPointerUp );
@@ -546,7 +574,7 @@
 
 			}
 
-			function mousewheel( event ) {
+			function onMouseWheel( event ) {
 
 				if ( scope.enabled === false ) return;
 				if ( scope.noZoom === true ) return;
@@ -576,17 +604,16 @@
 
 			}
 
-			function touchstart( event ) {
+			function onTouchStart( event ) {
 
-				if ( scope.enabled === false ) return;
-				event.preventDefault();
+				trackPointer( event );
 
-				switch ( event.touches.length ) {
+				switch ( _pointers.length ) {
 
 					case 1:
 						_state = STATE.TOUCH_ROTATE;
 
-						_moveCurr.copy( getMouseOnCircle( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ) );
+						_moveCurr.copy( getMouseOnCircle( _pointers[ 0 ].pageX, _pointers[ 0 ].pageY ) );
 
 						_movePrev.copy( _moveCurr );
 
@@ -595,11 +622,11 @@
 					default:
 						// 2 or more
 						_state = STATE.TOUCH_ZOOM_PAN;
-						const dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX;
-						const dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY;
+						const dx = _pointers[ 0 ].pageX - _pointers[ 1 ].pageX;
+						const dy = _pointers[ 0 ].pageY - _pointers[ 1 ].pageY;
 						_touchZoomDistanceEnd = _touchZoomDistanceStart = Math.sqrt( dx * dx + dy * dy );
-						const x = ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX ) / 2;
-						const y = ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY ) / 2;
+						const x = ( _pointers[ 0 ].pageX + _pointers[ 1 ].pageX ) / 2;
+						const y = ( _pointers[ 0 ].pageY + _pointers[ 1 ].pageY ) / 2;
 
 						_panStart.copy( getMouseOnScreen( x, y ) );
 
@@ -613,27 +640,27 @@
 
 			}
 
-			function touchmove( event ) {
+			function onTouchMove( event ) {
 
-				if ( scope.enabled === false ) return;
-				event.preventDefault();
+				trackPointer( event );
 
-				switch ( event.touches.length ) {
+				switch ( _pointers.length ) {
 
 					case 1:
 						_movePrev.copy( _moveCurr );
 
-						_moveCurr.copy( getMouseOnCircle( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ) );
+						_moveCurr.copy( getMouseOnCircle( event.pageX, event.pageY ) );
 
 						break;
 
 					default:
 						// 2 or more
-						const dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX;
-						const dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY;
+						const position = getSecondPointerPosition( event );
+						const dx = event.pageX - position.x;
+						const dy = event.pageY - position.y;
 						_touchZoomDistanceEnd = Math.sqrt( dx * dx + dy * dy );
-						const x = ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX ) / 2;
-						const y = ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY ) / 2;
+						const x = ( event.pageX + position.x ) / 2;
+						const y = ( event.pageY + position.y ) / 2;
 
 						_panEnd.copy( getMouseOnScreen( x, y ) );
 
@@ -643,11 +670,9 @@
 
 			}
 
-			function touchend( event ) {
-
-				if ( scope.enabled === false ) return;
+			function onTouchEnd( event ) {
 
-				switch ( event.touches.length ) {
+				switch ( _pointers.length ) {
 
 					case 0:
 						_state = STATE.NONE;
@@ -656,7 +681,7 @@
 					case 1:
 						_state = STATE.TOUCH_ROTATE;
 
-						_moveCurr.copy( getMouseOnCircle( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ) );
+						_moveCurr.copy( getMouseOnCircle( event.pageX, event.pageY ) );
 
 						_movePrev.copy( _moveCurr );
 
@@ -675,16 +700,58 @@
 
 			}
 
+			function addPointer( event ) {
+
+				_pointers.push( event );
+
+			}
+
+			function removePointer( event ) {
+
+				delete _pointerPositions[ event.pointerId ];
+
+				for ( let i = 0; i < _pointers.length; i ++ ) {
+
+					if ( _pointers[ i ].pointerId == event.pointerId ) {
+
+						_pointers.splice( i, 1 );
+
+						return;
+
+					}
+
+				}
+
+			}
+
+			function trackPointer( event ) {
+
+				let position = _pointerPositions[ event.pointerId ];
+
+				if ( position === undefined ) {
+
+					position = new THREE.Vector2();
+					_pointerPositions[ event.pointerId ] = position;
+
+				}
+
+				position.set( event.pageX, event.pageY );
+
+			}
+
+			function getSecondPointerPosition( event ) {
+
+				const pointer = event.pointerId === _pointers[ 0 ].pointerId ? _pointers[ 1 ] : _pointers[ 0 ];
+				return _pointerPositions[ pointer.pointerId ];
+
+			}
+
 			this.dispose = function () {
 
 				scope.domElement.removeEventListener( 'contextmenu', contextmenu );
 				scope.domElement.removeEventListener( 'pointerdown', onPointerDown );
-				scope.domElement.removeEventListener( 'wheel', mousewheel );
-				scope.domElement.removeEventListener( 'touchstart', touchstart );
-				scope.domElement.removeEventListener( 'touchend', touchend );
-				scope.domElement.removeEventListener( 'touchmove', touchmove );
-				scope.domElement.ownerDocument.removeEventListener( 'pointermove', onPointerMove );
-				scope.domElement.ownerDocument.removeEventListener( 'pointerup', onPointerUp );
+				scope.domElement.removeEventListener( 'pointercancel', onPointerCancel );
+				scope.domElement.removeEventListener( 'wheel', onMouseWheel );
 				window.removeEventListener( 'keydown', keydown );
 				window.removeEventListener( 'keyup', keyup );
 
@@ -692,18 +759,10 @@
 
 			this.domElement.addEventListener( 'contextmenu', contextmenu );
 			this.domElement.addEventListener( 'pointerdown', onPointerDown );
-			this.domElement.addEventListener( 'wheel', mousewheel, {
-				passive: false
-			} );
-			this.domElement.addEventListener( 'touchstart', touchstart, {
-				passive: false
-			} );
-			this.domElement.addEventListener( 'touchend', touchend );
-			this.domElement.addEventListener( 'touchmove', touchmove, {
+			this.domElement.addEventListener( 'pointercancel', onPointerCancel );
+			this.domElement.addEventListener( 'wheel', onMouseWheel, {
 				passive: false
 			} );
-			this.domElement.ownerDocument.addEventListener( 'pointermove', onPointerMove );
-			this.domElement.ownerDocument.addEventListener( 'pointerup', onPointerUp );
 			window.addEventListener( 'keydown', keydown );
 			window.addEventListener( 'keyup', keyup );
 			this.handleResize(); // force an update at start

+ 122 - 64
examples/jsm/controls/TrackballControls.js

@@ -24,6 +24,7 @@ class TrackballControls extends EventDispatcher {
 
 		this.object = object;
 		this.domElement = domElement;
+		this.domElement.style.touchAction = 'none'; // disable touch scroll
 
 		// API
 
@@ -77,7 +78,10 @@ class TrackballControls extends EventDispatcher {
 			_zoomEnd = new Vector2(),
 
 			_panStart = new Vector2(),
-			_panEnd = new Vector2();
+			_panEnd = new Vector2(),
+
+			_pointers = [],
+			_pointerPositions = {};
 
 		// for reset
 
@@ -406,14 +410,24 @@ class TrackballControls extends EventDispatcher {
 
 			if ( scope.enabled === false ) return;
 
-			switch ( event.pointerType ) {
+			if ( _pointers.length === 0 ) {
 
-				case 'mouse':
-				case 'pen':
-					onMouseDown( event );
-					break;
+				scope.domElement.ownerDocument.addEventListener( 'pointermove', onPointerMove );
+				scope.domElement.ownerDocument.addEventListener( 'pointerup', onPointerUp );
+
+			}
+
+			//
+
+			addPointer( event );
+
+			if ( event.pointerType === 'touch' ) {
+
+				onTouchStart( event );
+
+			} else {
 
-				// TODO touch
+				onMouseDown( event );
 
 			}
 
@@ -423,14 +437,13 @@ class TrackballControls extends EventDispatcher {
 
 			if ( scope.enabled === false ) return;
 
-			switch ( event.pointerType ) {
+			if ( event.pointerType === 'touch' ) {
 
-				case 'mouse':
-				case 'pen':
-					onMouseMove( event );
-					break;
+				onTouchMove( event );
+
+			} else {
 
-				// TODO touch
+				onMouseMove( event );
 
 			}
 
@@ -440,17 +453,34 @@ class TrackballControls extends EventDispatcher {
 
 			if ( scope.enabled === false ) return;
 
-			switch ( event.pointerType ) {
+			if ( event.pointerType === 'touch' ) {
 
-				case 'mouse':
-				case 'pen':
-					onMouseUp();
-					break;
+				onTouchEnd( event );
+
+			} else {
+
+				onMouseUp( event );
+
+			}
 
-				// TODO touch
+			//
+
+			removePointer( event );
+
+			if ( _pointers.length === 0 ) {
+
+				scope.domElement.ownerDocument.removeEventListener( 'pointermove', onPointerMove );
+				scope.domElement.ownerDocument.removeEventListener( 'pointerup', onPointerUp );
 
 			}
 
+
+		}
+
+		function onPointerCancel( event ) {
+
+			removePointer( event );
+
 		}
 
 		function keydown( event ) {
@@ -542,8 +572,6 @@ class TrackballControls extends EventDispatcher {
 
 		function onMouseMove( event ) {
 
-			if ( scope.enabled === false ) return;
-
 			const state = ( _keyState !== STATE.NONE ) ? _keyState : _state;
 
 			if ( state === STATE.ROTATE && ! scope.noRotate ) {
@@ -565,8 +593,6 @@ class TrackballControls extends EventDispatcher {
 
 		function onMouseUp() {
 
-			if ( scope.enabled === false ) return;
-
 			_state = STATE.NONE;
 
 			scope.domElement.ownerDocument.removeEventListener( 'pointermove', onPointerMove );
@@ -576,7 +602,7 @@ class TrackballControls extends EventDispatcher {
 
 		}
 
-		function mousewheel( event ) {
+		function onMouseWheel( event ) {
 
 			if ( scope.enabled === false ) return;
 
@@ -608,28 +634,26 @@ class TrackballControls extends EventDispatcher {
 
 		}
 
-		function touchstart( event ) {
+		function onTouchStart( event ) {
 
-			if ( scope.enabled === false ) return;
-
-			event.preventDefault();
+			trackPointer( event );
 
-			switch ( event.touches.length ) {
+			switch ( _pointers.length ) {
 
 				case 1:
 					_state = STATE.TOUCH_ROTATE;
-					_moveCurr.copy( getMouseOnCircle( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ) );
+					_moveCurr.copy( getMouseOnCircle( _pointers[ 0 ].pageX, _pointers[ 0 ].pageY ) );
 					_movePrev.copy( _moveCurr );
 					break;
 
 				default: // 2 or more
 					_state = STATE.TOUCH_ZOOM_PAN;
-					const dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX;
-					const dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY;
+					const dx = _pointers[ 0 ].pageX - _pointers[ 1 ].pageX;
+					const dy = _pointers[ 0 ].pageY - _pointers[ 1 ].pageY;
 					_touchZoomDistanceEnd = _touchZoomDistanceStart = Math.sqrt( dx * dx + dy * dy );
 
-					const x = ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX ) / 2;
-					const y = ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY ) / 2;
+					const x = ( _pointers[ 0 ].pageX + _pointers[ 1 ].pageX ) / 2;
+					const y = ( _pointers[ 0 ].pageY + _pointers[ 1 ].pageY ) / 2;
 					_panStart.copy( getMouseOnScreen( x, y ) );
 					_panEnd.copy( _panStart );
 					break;
@@ -640,26 +664,27 @@ class TrackballControls extends EventDispatcher {
 
 		}
 
-		function touchmove( event ) {
+		function onTouchMove( event ) {
 
-			if ( scope.enabled === false ) return;
-
-			event.preventDefault();
+			trackPointer( event );
 
-			switch ( event.touches.length ) {
+			switch ( _pointers.length ) {
 
 				case 1:
 					_movePrev.copy( _moveCurr );
-					_moveCurr.copy( getMouseOnCircle( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ) );
+					_moveCurr.copy( getMouseOnCircle( event.pageX, event.pageY ) );
 					break;
 
 				default: // 2 or more
-					const dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX;
-					const dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY;
+
+					const position = getSecondPointerPosition( event );
+
+					const dx = event.pageX - position.x;
+					const dy = event.pageY - position.y;
 					_touchZoomDistanceEnd = Math.sqrt( dx * dx + dy * dy );
 
-					const x = ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX ) / 2;
-					const y = ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY ) / 2;
+					const x = ( event.pageX + position.x ) / 2;
+					const y = ( event.pageY + position.y ) / 2;
 					_panEnd.copy( getMouseOnScreen( x, y ) );
 					break;
 
@@ -667,11 +692,9 @@ class TrackballControls extends EventDispatcher {
 
 		}
 
-		function touchend( event ) {
-
-			if ( scope.enabled === false ) return;
+		function onTouchEnd( event ) {
 
-			switch ( event.touches.length ) {
+			switch ( _pointers.length ) {
 
 				case 0:
 					_state = STATE.NONE;
@@ -679,7 +702,7 @@ class TrackballControls extends EventDispatcher {
 
 				case 1:
 					_state = STATE.TOUCH_ROTATE;
-					_moveCurr.copy( getMouseOnCircle( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ) );
+					_moveCurr.copy( getMouseOnCircle( event.pageX, event.pageY ) );
 					_movePrev.copy( _moveCurr );
 					break;
 
@@ -697,19 +720,59 @@ class TrackballControls extends EventDispatcher {
 
 		}
 
+		function addPointer( event ) {
+
+			_pointers.push( event );
+
+		}
+
+		function removePointer( event ) {
+
+			delete _pointerPositions[ event.pointerId ];
+
+			for ( let i = 0; i < _pointers.length; i ++ ) {
+
+				if ( _pointers[ i ].pointerId == event.pointerId ) {
+
+					_pointers.splice( i, 1 );
+					return;
+
+				}
+
+			}
+
+		}
+
+		function trackPointer( event ) {
+
+			let position = _pointerPositions[ event.pointerId ];
+
+			if ( position === undefined ) {
+
+				position = new Vector2();
+				_pointerPositions[ event.pointerId ] = position;
+
+			}
+
+			position.set( event.pageX, event.pageY );
+
+		}
+
+		function getSecondPointerPosition( event ) {
+
+			const pointer = ( event.pointerId === _pointers[ 0 ].pointerId ) ? _pointers[ 1 ] : _pointers[ 0 ];
+
+			return _pointerPositions[ pointer.pointerId ];
+
+		}
+
 		this.dispose = function () {
 
 			scope.domElement.removeEventListener( 'contextmenu', contextmenu );
 
 			scope.domElement.removeEventListener( 'pointerdown', onPointerDown );
-			scope.domElement.removeEventListener( 'wheel', mousewheel );
-
-			scope.domElement.removeEventListener( 'touchstart', touchstart );
-			scope.domElement.removeEventListener( 'touchend', touchend );
-			scope.domElement.removeEventListener( 'touchmove', touchmove );
-
-			scope.domElement.ownerDocument.removeEventListener( 'pointermove', onPointerMove );
-			scope.domElement.ownerDocument.removeEventListener( 'pointerup', onPointerUp );
+			scope.domElement.removeEventListener( 'pointercancel', onPointerCancel );
+			scope.domElement.removeEventListener( 'wheel', onMouseWheel );
 
 			window.removeEventListener( 'keydown', keydown );
 			window.removeEventListener( 'keyup', keyup );
@@ -719,14 +782,9 @@ class TrackballControls extends EventDispatcher {
 		this.domElement.addEventListener( 'contextmenu', contextmenu );
 
 		this.domElement.addEventListener( 'pointerdown', onPointerDown );
-		this.domElement.addEventListener( 'wheel', mousewheel, { passive: false } );
-
-		this.domElement.addEventListener( 'touchstart', touchstart, { passive: false } );
-		this.domElement.addEventListener( 'touchend', touchend );
-		this.domElement.addEventListener( 'touchmove', touchmove, { passive: false } );
+		this.domElement.addEventListener( 'pointercancel', onPointerCancel );
+		this.domElement.addEventListener( 'wheel', onMouseWheel, { passive: false } );
 
-		this.domElement.ownerDocument.addEventListener( 'pointermove', onPointerMove );
-		this.domElement.ownerDocument.addEventListener( 'pointerup', onPointerUp );
 
 		window.addEventListener( 'keydown', keydown );
 		window.addEventListener( 'keyup', keyup );