Browse Source

Add pinch

Add zoom or unzoom action when user make pinch open or pinch close on touch screen.
Work well on iOS 8 (iPad 2) and Android 4.0.4 (Samsung Galaxy Tab 2).
Eucly2 11 years ago
parent
commit
0eadd521b2
1 changed files with 96 additions and 2 deletions
  1. 96 2
      Babylon/Cameras/babylon.arcRotateCamera.ts

+ 96 - 2
Babylon/Cameras/babylon.arcRotateCamera.ts

@@ -47,6 +47,19 @@
         private _previousAlpha: number;
         private _previousBeta: number;
         private _previousRadius: number;
+		
+		// Pinch
+		// value for pinch step scaling
+		// set to 20 by default
+		public pinchPrecision = 20;
+		// Event for pinch
+		private _touchStart: (e: PointerEvent) => void;
+		private _touchMove: (e: PointerEvent) => void;
+		private _touchEnd: (e: PointerEvent) => void;
+		// Method for pinch
+		private _pinchStart: (e: PointerEvent) => void;
+		private _pinchMove: (e: PointerEvent) => void;
+		private _pinchEnd: (e: PointerEvent) => void;
 
         constructor(name: string, public alpha: number, public beta: number, public radius: number, public target: any, scene: Scene) {
             super(name, BABYLON.Vector3.Zero(), scene);
@@ -93,7 +106,12 @@
         public attachControl(element: HTMLElement, noPreventDefault?: boolean): void {
             var previousPosition;
             var pointerId;
-
+			// to know if pinch started
+			var pinchStarted = false;
+			// two pinch point on X
+			// that will use for find if user action is pinch open or pinch close
+			var pinchPointX1, pinchPointX2;
+			
             if (this._attachedElement) {
                 return;
             }
@@ -137,6 +155,11 @@
                     if (pointerId !== evt.pointerId) {
                         return;
                     }
+					
+					// return pinch is started
+					if (pinchStarted){
+                        return;
+                    }
 
                     var offsetX = evt.clientX - previousPosition.x;
                     var offsetY = evt.clientY - previousPosition.y;
@@ -158,6 +181,11 @@
                     if (!engine.isPointerLock) {
                         return;
                     }
+					
+					// return pinch is started
+					if (pinchStarted){
+                        return;
+                    }
 
                     var offsetX = evt.movementX || evt.mozMovementX || evt.webkitMovementX || evt.msMovementX || 0;
                     var offsetY = evt.movementY || evt.mozMovementY || evt.webkitMovementY || evt.msMovementY || 0;
@@ -264,6 +292,64 @@
                     previousPosition = null;
                     pointerId = null;
                 };
+				
+				this._touchStart = event => {
+                    if (event.touches.length == 2) {
+                        //-- start pinch if two fingers on the screen
+                        pinchStarted = true;
+                        this._pinchStart(event);
+                    } 
+                };
+				this._touchMove = event => {
+                    if (pinchStarted) {
+                        //-- make scaling
+                        this._pinchMove(event);
+                    }
+                };
+				this._touchEnd = event => {
+                    if (pinchStarted) {
+                        //-- end of pinch
+                        this._pinchEnd(event);
+                    } 
+                };
+				
+				this._pinchStart = event => {
+                    // save origin touch point
+                    pinchPointX1 = event.touches[0].clientX;
+                    pinchPointX2 = event.touches[1].clientX;
+                    // block the camera 
+                    // if not it rotate around target during pinch
+                    pinchStarted = true;
+                };
+				this._pinchMove = event => {
+                    // variable for new camera's radius
+                    var delta = 0;
+                    // variables to know if pinch open or pinch close
+                    var direction = 1;
+                    var distanceXOrigine, distanceXNow;
+                    
+                    if (event.touches.length != 2)
+                        return;
+                    // calculate absolute distances of the two fingers
+                    distanceXOrigine = Math.abs(pinchPointX1 - pinchPointX2);
+                    distanceXNow = Math.abs(event.touches[0].clientX - event.touches[1].clientX);
+                    
+                    // if distanceXNow < distanceXOrigine -> pinch close so direction = -1
+                    if (distanceXNow < distanceXOrigine) {
+                        direction = -1;
+                    }
+                    // calculate new radius
+                    delta = (this.pinchPrecision / (this.wheelPrecision * 40)) * direction;
+                    // set new radius
+                    this.inertialRadiusOffset += delta;
+                    // save origin touch point
+                    pinchPointX1 = event.touches[0].clientX;
+                    pinchPointX2 = event.touches[1].clientX;
+                };
+				this._pinchEnd = event => {
+                    // cancel pinch and deblock camera rotation
+                    pinchStarted = false;
+                };
             }
 
             element.addEventListener(eventPrefix + "down", this._onPointerDown, false);
@@ -275,6 +361,10 @@
             element.addEventListener("MSGestureChange", this._onGesture, false);
             element.addEventListener('mousewheel', this._wheel, false);
             element.addEventListener('DOMMouseScroll', this._wheel, false);
+			// pinch
+            element.addEventListener('touchstart', this._touchStart, false);
+            element.addEventListener('touchmove', this._touchMove, false);
+            element.addEventListener('touchend', this._touchEnd, false);
 
             Tools.RegisterTopRootEvents([
                 { name: "keydown", handler: this._onKeyDown },
@@ -297,6 +387,10 @@
             element.removeEventListener("MSGestureChange", this._onGesture);
             element.removeEventListener('mousewheel', this._wheel);
             element.removeEventListener('DOMMouseScroll', this._wheel);
+			// pinch
+            element.removeEventListener('touchstart', this._touchStart);
+            element.removeEventListener('touchmove', this._touchMove);
+            element.removeEventListener('touchend', this._touchEnd);
 
             Tools.UnregisterTopRootEvents([
                 { name: "keydown", handler: this._onKeyDown },
@@ -455,4 +549,4 @@
             this.maxZ = distance * 2;
         }
     }
-} 
+}