Das Thema Gestures und Multitouch im Flash Player 10.1 und AIR 2 hatte ich bereits vorgestellt. Heute möchte ich im Speziellen auf die „Pan”-Geste eingehen, also das Scrollen mit zwei Fingern (TransformGestureEvent.GESTURE_PAN). Landläufig könnte man es auch als „Wischen” mit 2 Fingern bezeichnen (manchmal auch Swipe, obwohl Adobe darunter die 3-Fingergeste versteht).

Die folgenden Beispielklassen zeigen, wie es möglich, zu erkennen, ob der Nutzer nach rechts, links, oben oder unten gewischt hat.

Dazu habe ich mir eine kleine Hilfsklasse gebaut. Sie wird als Event Handler benutzt und erfasst die Geste. Eine Geste hat 3 Phasen: GesturePhase.BEGIN, GesturePhase.UPDATE und GesturePhase.END. Die Update-Phase wird mehrmals ausgelöst, so ca. 15-20x bei einem „Wisch”.

Zählt man nun, wie oft der Offset zwischen den Events in x- und y-Richtung ungleich 0 ist, erkennt man, in welche Richtung die Finger sich bewegt haben. So bedeutet zum Beispiel offsetX:-1.234 und offsetY:0 eine horizontale Bewegung. Sie wird als „1x horizontal” gespeichert.

Letztendlich kann dann nach Beenden der Geste (GesturePhase.END) ausgewertet werden. Es kommt z.B. 20x horizontal und 3x vertikal als Ergebnis für ein Wischen, woraus man schließen kann, dass der Nutzer horizontal gemeint hat (und die 3x vertikal lediglich eine Ungenauigkeit sind).

Summiert man sich die ganzen Offsets, kann man am Vorzeichen der Summe nun die Richtung erkennen (bei horizontal ob links/rechts, bei vertikal ob oben/unten).

Demo-Klasse

Hier die Demo-Anwendung.

Actionscript:
  1. package
  2. {
  3.     import flash.display.Sprite;
  4.     import flash.events.GesturePhase;
  5.     import flash.events.TransformGestureEvent;
  6.     import flash.text.TextField;
  7.    
  8.     public class PanGestureDemo extends Sprite {
  9.  
  10.         private var tf:TextField = new TextField();
  11.         private var panGestureDirection:PanGestureDirection = new PanGestureDirection();
  12.        
  13.         public function PanGestureDemo(){   
  14.             addChild(tf);
  15.             tf.x = 20;
  16.             tf.y = 20;
  17.             tf.width = 300;
  18.             tf.height = 50;
  19.            
  20.             panGestureDirection.addEventListener(PanGestureDirectionEvent.LEFT, onLeft);
  21.             panGestureDirection.addEventListener(PanGestureDirectionEvent.RIGHT, onRight);
  22.             panGestureDirection.addEventListener(PanGestureDirectionEvent.UP, onUp);
  23.             panGestureDirection.addEventListener(PanGestureDirectionEvent.DOWN, onDown);
  24.            
  25.             this.stage.addEventListener(TransformGestureEvent.GESTURE_PAN, panGestureDirection.onPanEvent);
  26.         }
  27.        
  28.         private function onLeft(evt:PanGestureDirectionEvent):void {           
  29.             tf.text = "on left";
  30.         }
  31.  
  32.         private function onRight(evt:PanGestureDirectionEvent):void {         
  33.             tf.text = "on right";
  34.         }
  35.  
  36.         private function onUp(evt:PanGestureDirectionEvent):void {     
  37.             tf.text = "on up";
  38.         }
  39.  
  40.         private function onDown(evt:PanGestureDirectionEvent):void {           
  41.             tf.text = "on down";
  42.         }
  43.     }
  44. }

Klasse zum Erkennen der Pan-Richtung

Actionscript:
  1. package
  2. {
  3.     import flash.events.EventDispatcher;
  4.     import flash.events.GesturePhase;
  5.     import flash.events.TransformGestureEvent;
  6.  
  7.     /**
  8.      * Detects the direction of the Pan gesture and dispatches a PanGestureDirectEvent
  9.      *
  10.      */ 
  11.     public class PanGestureDirection extends EventDispatcher
  12.     {
  13.                
  14.         // count horizontal and vertical gestures
  15.         private var countX:int = 0;
  16.         private var countY:int = 0;
  17.  
  18.         // sum up the offsets of the pan event
  19.         private var sum_offsetX:int = 0;
  20.         private var sum_offsetY:int= 0;
  21.        
  22.    
  23.         public function PanGestureDirection() {
  24.         }
  25.        
  26.         /**
  27.          * Use this function as event handler for the 
  28.          * TransformGestureEvent of your object
  29.          *
  30.          * @param evt
  31.          *
  32.          */  
  33.         public function onPanEvent(evt:TransformGestureEvent):void {
  34.                    
  35.             if (evt.phase==GesturePhase.BEGIN) {
  36.             }
  37.            
  38.             if (evt.phase==GesturePhase.UPDATE) {
  39.                 onUpdate(evt.offsetX, evt.offsetY);
  40.                
  41.             }
  42.             if (evt.phase==GesturePhase.END) {
  43.                 dispatchResult();
  44.             }         
  45.         }
  46.        
  47.         /**
  48.          * On every update event store the value and count the used direction
  49.          * @param offsetX
  50.          * @param offsetY
  51.          *
  52.          */  
  53.         private function onUpdate(offsetX:int, offsetY:int):void {
  54.             if (offsetX != 0) {      
  55.                 sum_offsetX += offsetX;
  56.                 countX += 1;
  57.                
  58.             }
  59.             if (offsetY != 0) {      
  60.                 sum_offsetY += offsetY;
  61.                 countY += 1;
  62.             }
  63.        
  64.         }
  65.        
  66.         /**
  67.          * Detect pan direction and dispatch event
  68.          *
  69.          */  
  70.         public function dispatchResult():void {
  71.            
  72.             var eventType:String = "";
  73.            
  74.             if (countX> countY) {
  75.                 // horizontal
  76.                 if (sum_offsetX> 0) {
  77.                     eventType = PanGestureDirectionEvent.RIGHT;
  78.                 } else {
  79.                     eventType = PanGestureDirectionEvent.LEFT;
  80.                 }
  81.                
  82.                
  83.             } else {
  84.                 // vertical
  85.                 if (sum_offsetY> 0) {
  86.                     eventType = PanGestureDirectionEvent.DOWN;
  87.                 } else {
  88.                     eventType = PanGestureDirectionEvent.UP;
  89.                 }                  
  90.             }
  91.            
  92.             reset();
  93.            
  94.             var resultEvent:PanGestureDirectionEvent = new PanGestureDirectionEvent(eventType);
  95.             dispatchEvent (resultEvent);   
  96.            
  97.         }
  98.        
  99.        
  100.         /**
  101.          * Reset the variables
  102.          *
  103.          */  
  104.         private function reset():void {
  105.             sum_offsetX = 0;
  106.             sum_offsetY= 0;
  107.             countX = 0;
  108.             countY = 0;    
  109.         }
  110.        
  111.     }
  112. }

Event

Actionscript:
  1. package
  2. {
  3.     import flash.events.Event;
  4.    
  5.     public class PanGestureDirectionEvent extends Event
  6.     {
  7.        
  8.         public static const UP:String = "panGestureUp";
  9.         public static const DOWN:String = "panGestureDown";
  10.         public static const RIGHT:String = "panGestureRight";
  11.         public static const LEFT:String = "panGestureLeft";  
  12.        
  13.         public function PanGestureDirectionEvent(type:String, bubbles:Boolean=false, cancelable:Boolean=false)
  14.         {
  15.             super(type, bubbles, cancelable);
  16.         }
  17.     }
  18. }