Advertisement
photokandy

Simple Gesture Recognition

Jul 20th, 2012
140
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /*jshint asi:true, forin:true, noarg:true, noempty:true, eqeqeq:false, bitwise:true, undef:true, curly:true, browser:true, devel:true, smarttabs:true, maxerr:50 */
  2. /******************************************************************************
  3.  *
  4.  * UI-GESTURES
  5.  * Author:  Kerri Shotts
  6.  * Version: 0.1 alpha
  7.  * License: MIT
  8.  *
  9.  * A simple, no-frills gesture recognizer. Permits long-press recognition,
  10.  * horizontal swipe recognition, and vertical swipe recognition. Recognizing
  11.  * swipes in a particular direction (left, right, up, down) should be easy to
  12.  * add later.
  13.  *
  14.  * The SimpleGesture class represents the basic recognizer -- it implements all
  15.  * the tracking of touch and mouse events. Every 100ms it calls
  16.  * a recognition function, which by default does nothing. Essentially, Simple-
  17.  * Gesture is abstract. This method is expected to be overridden by a specific
  18.  * recognizer, which the LongPressGesture, HorizontalSwipeGesture, and
  19.  * VerticalSwipeGesture do.
  20.  *
  21.  * The LongPressGesture will fire off an event when a longpress is recognized.
  22.  * How this is recognized is partially defined by the caller -- that is,
  23.  * two durations can be supplied. By default, the long-press is recognized at
  24.  * 1s and cancelled at 3s (assuming no previous recognition). It is also
  25.  * cancelled should any movement outside of a 25px radius occur.
  26.  *
  27.  * The HorizontalSwipeGesture and VerticalSwipeGesture will fire off an event
  28.  * when a swipe in the given axis is detected. This swipe is detected when the
  29.  * length of the swipe exceeds 75px (or the provided override), and will be
  30.  * fired as long as the duration of the swipe is less than the cancel duration
  31.  * (3s by default). The line must not deviate by more than 25px in the specified
  32.  * axis, or the gesture will fail to be recognized.
  33.  *
  34.  * Usage:
  35.  *
  36.  * var anElement = document.getElementById("abc");
  37.  * var aLongPressGesture = new GESTURES.LongPressGesture
  38.  *                             ( anElement, theFunctionToCallWhenRecognized,
  39.  *                               [ thePressDuration, [ theCancelDelay ]] );
  40.  *
  41.  * var aHorizontalSwipeGesture = new GESTURES.HorizontalSwipeGesture
  42.  *                               ( anElement, theFunctionToCallWhenRecognized,
  43.  *                                 [ theSwipeLength, [ theCancelDelay ]] );
  44.  *
  45.  * var aVerticalSwipeGesture = new GESTURES.VerticalSwipeGesture
  46.  *                             ( anElement, theFunctionToCallWhenRecognized,
  47.  *                               [ theSwipeLength, [ theCancelDelay ]] );
  48.  *
  49.  *
  50.  * Where: anElement is an HTML DOM element
  51.  *        theFunctionToCallWhenRecognized is a function that will be called
  52.  *            when the gesture is recognized. It will be passed the recognizer,
  53.  *            and as such, one can store & retrieve data in this manner:
  54.  *
  55.  *                 aLongPressGesture.data = "Hello";
  56.  *                 function theFunctionToCallWhenRecognized ( gr )
  57.  *                 { alert (gr.data); }
  58.  *
  59.  *            This will generate an alert of "Hello" when the element is long-
  60.  *            pressed.
  61.  *
  62.  *        thePressDuration: Optional, defaults to 1s. The amount of time required
  63.  *            to recognize a long-press.
  64.  *        theSwipeLength: Optional, defaults to 75px. The length of a swipe
  65.  *            required to recognize a swipe.
  66.  *        theCancelDelay: Optional, defaults to 3s. If a gesture is not recognized
  67.  *            prior to this delay, the gesture is cancelled, that is, it will
  68.  *            never be recognized.
  69.  *
  70.  ******************************************************************************/
  71.  
  72. var GESTURES = GESTURES || {};  // create the namespace
  73.  
  74. GESTURES.SimpleGesture = function ( element )
  75. {
  76.   var self = this;
  77.  
  78.   self.theElement = {};
  79.  
  80.   self._touchStartX = 0;
  81.   self._touchStartY = 0;
  82.   self._touchX = 0;
  83.   self._touchY = 0;
  84.   self._deltaX = 0;
  85.   self._deltaY = 0;
  86.   self._duration = 0;
  87.   self._timerId = -1;
  88.   self._distance = 0;
  89.   self._event = {};
  90.   self._cleared = false;
  91.  
  92.   self.attachToElement = function ( element )
  93.   {
  94.     // get our element
  95.     self.theElement = element;
  96.     // attach our listeners
  97.     self.theElement.addEventListener ( "touchstart", self.touchStart, false );
  98.     self.theElement.addEventListener ( "touchmove",  self.touchMove , false );
  99.     self.theElement.addEventListener ( "touchend",   self.touchEnd,   false );
  100.  
  101.     self.theElement.addEventListener ( "mousedown",  self.mouseDown,  false );
  102.     self.theElement.addEventListener ( "mousemove",  self.mouseMove,  false );
  103.     self.theElement.addEventListener ( "mouseup",    self.mouseUp,    false );
  104.    
  105.   }
  106.  
  107.   self.recognizeGesture = function ( o )
  108.   {
  109.     // we do nothing; no gesture to recognize.
  110.     console.log ("default recognizer...");
  111.   }
  112.  
  113.   self.attachGestureRecognizer = function ( fn )
  114.   {
  115.     self.recognizeGesture = fn;
  116.   }
  117.  
  118.   self.updateGesture = function ()
  119.   {
  120.     self._duration += 100;
  121.     self._distance = Math.sqrt((self._deltaX * self._deltaX) +
  122.                             (self._deltaY * self._deltaY));
  123.                             console.log ( self._duration );
  124.     console.log ("gesture: start: (" + self._touchStartX +
  125.                                  "," + self._touchStartY +
  126.                       ") current: (" + self._touchX +
  127.                                  "," + self._touchY +
  128.                         ") delta: (" + self._deltaX +
  129.                                  "," + self._deltaY +
  130.                          ") delay: " + self._duration +
  131.                               "ms, " + self._distance + "px");
  132.     if (!self._cleared)
  133.     {
  134.       self.recognizeGesture( self );
  135.     }
  136.   }
  137.  
  138.   self.clearEvent = function ()
  139.   {
  140.     if (self._cleared)
  141.     {
  142.         if (self._event.cancelBubble)
  143.         {
  144.           self._event.cancelBubble();
  145.         }
  146.         if (self._event.stopPropagation)
  147.         {
  148.           self._event.stopPropagation();
  149.         }
  150.         if (self._event.preventDefault)
  151.         {
  152.           self._event.preventDefault();
  153.         }
  154.         else
  155.         {
  156.           self._event.returnValue = false;
  157.         }
  158.     }
  159.     if (self._timerId>-1)
  160.     {
  161.       clearInterval (self._timerId);
  162.       self._timerId = -1;
  163.     }
  164.     self._cleared = true;
  165.   }
  166.  
  167.   self.eventStart = function ()
  168.   {
  169.     console.log ("eventstart");
  170.     self._duration = 0;
  171.     self._deltaX = 0;
  172.     self._deltaY = 0;
  173.     self._cleared = false;
  174.     self._touchStartX = self._touchX;
  175.     self._touchStartY = self._touchY;
  176.     self._timerId = setInterval ( self.updateGesture, 100 );
  177.   }
  178.  
  179.   self.touchStart = function (event)
  180.   {
  181.     console.log ("touchstart");
  182.     if (event)
  183.     {
  184.       self._touchX = event.touches[0].screenX;
  185.       self._touchY = event.touches[0].screenY;
  186.       self._event = event;
  187.     }
  188.     else
  189.     {
  190.       self._touchX = window.event.screenX;
  191.       self._touchY = window.event.screenY;
  192.       self._event = window.event;
  193.     }
  194.     self.eventStart();
  195.   }
  196.  
  197.   self.mouseDown = function (event)
  198.   {
  199.     console.log ("mousedown");
  200.     if (event)
  201.     {
  202.       self._touchX = event.screenX;
  203.       self._touchY = event.screenY;
  204.       self._event = event;
  205.     }
  206.     else
  207.     {
  208.       self._touchX = window.event.screenX;
  209.       self._touchY = window.event.screenY;
  210.       self._event = window.event;
  211.     }
  212.     self.eventStart();
  213.   }
  214.  
  215.   self.eventMove = function ()
  216.   {
  217.     console.log ("eventmove");
  218.     self._deltaX = self._touchX - self._touchStartX;
  219.     self._deltaY = self._touchY - self._touchStartY;
  220.    
  221.     var distance = Math.sqrt((self._deltaX * self._deltaX) +
  222.                             (self._deltaY * self._deltaY));
  223.  
  224.   }
  225.  
  226.   self.touchMove = function (event)
  227.   {
  228.     console.log ("touchmove");
  229.     if (event)
  230.     {
  231.       self._touchX = event.touches[0].screenX;
  232.       self._touchY = event.touches[0].screenY;
  233.       self._event = event;
  234.     }
  235.     else
  236.     {
  237.       self._touchX = window.event.screenX;
  238.       self._touchY = window.event.screenY;
  239.       self._event = window.event;
  240.     }
  241.     self.eventMove();
  242.   }
  243.  
  244.   self.mouseMove = function (event)
  245.   {
  246.     console.log ("mousemove");
  247.     if (event)
  248.     {
  249.       self._touchX = event.screenX;
  250.       self._touchY = event.screenY;
  251.       self._event = event;
  252.     }
  253.     else
  254.     {
  255.       self._touchX = window.event.screenX;
  256.       self._touchY = window.event.screenY;
  257.       self._event = window.event;
  258.     }
  259.     self.eventMove();
  260.   }
  261.  
  262.   self.eventEnd = function ()
  263.   {
  264.     console.log ("eventend");
  265.     self.clearEvent();
  266.   }
  267.  
  268.   self.touchEnd = function (event)
  269.   {
  270.     console.log ("touchend");
  271.     self._event = event || window.event;
  272.     self.eventEnd();
  273.   }
  274.  
  275.   self.mouseUp = function (event)
  276.   {
  277.     console.log ("mouseup");
  278.     self._event = event || window.event;
  279.     self.eventEnd();
  280.   }
  281.  
  282.   // attach to the element passed in the constructor.
  283.   self.attachToElement ( element );
  284. }
  285.  
  286. GESTURES.LongPressGesture = function( element, whatToDo, delayToRecognition, delayToCancel )
  287. {
  288.   var myGesture = new GESTURES.SimpleGesture ( element );
  289.   myGesture._delayToRecognition = delayToRecognition || 1000;
  290.   myGesture._delayToCancel = delayToCancel || 3000;
  291.   myGesture._whatToDo = whatToDo;
  292.   myGesture.attachGestureRecognizer ( function ( o )
  293.   {
  294.     // no finger movement
  295.     if (o._distance < 25)
  296.     {
  297.       // must be between our minimum and maximum delay
  298.       if (o._duration >= o._delayToRecognition && o._duration <= o._delayToCancel )
  299.       {
  300.         // long-press recognized
  301.         o.clearEvent();
  302.         o._whatToDo( o );
  303.       }
  304.     }
  305.     else
  306.     {
  307.       o.clearEvent();
  308.       // long-press cancelled.
  309.     }
  310.   }
  311.   );
  312.   return myGesture;
  313. }
  314.  
  315. GESTURES.HorizontalSwipeGesture = function( element, whatToDo, radiusToRecognition, delayToCancel )
  316. {
  317.   var myGesture = new GESTURES.SimpleGesture ( element );
  318.   myGesture._radiusToRecognition = radiusToRecognition || 50;
  319.   myGesture._delayToCancel = delayToCancel || 3000;
  320.   myGesture._whatToDo = whatToDo;
  321.   myGesture.attachGestureRecognizer ( function ( o )
  322.   {
  323.     console.log ("horizontal recognizer...");
  324.     // no finger movement
  325.     if (o._distance > o._radiusToRecognition)
  326.     {
  327.       console.log ("1");
  328.       // must be between our minimum and maximum delay
  329.       if (o._duration <= o._delayToCancel )
  330.       {
  331.         console.log ("2");
  332.         // finger must trace a straight line
  333.         if ( Math.abs(o._deltaY) < 25 )
  334.         {
  335.           console.log ("3");
  336.           o.clearEvent();
  337.           console.log ("4");
  338.           o._whatToDo( o );
  339.         }
  340.       }
  341.     }
  342.   } );
  343.   return myGesture;
  344. }
  345.  
  346. GESTURES.VerticalSwipeGesture = function( element, whatToDo, radiusToRecognition, delayToCancel )
  347. {
  348.   var myGesture = new GESTURES.SimpleGesture ( element );
  349.   myGesture._radiusToRecognition = radiusToRecognition || 50;
  350.   myGesture._delayToCancel = delayToCancel || 3000;
  351.   myGesture._whatToDo = whatToDo;
  352.   myGesture.attachGestureRecognizer ( function ( o )
  353.   {
  354.     // no finger movement
  355.     if (o._distance > o._radiusToRecognition)
  356.     {
  357.       // must be between our minimum and maximum delay
  358.       if (o._duration <= o._delayToCancel )
  359.       {
  360.         // finger must trace a straight line
  361.         if ( Math.abs(o._deltaX) < 25 )
  362.         {
  363.           o.clearEvent();
  364.           o._whatToDo( o );
  365.         }
  366.       }
  367.     }
  368.   }
  369.   );
  370.   return myGesture;
  371. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement