[javascript] How to implement swipe gestures for mobile devices?

I have an application made in AngularJS which has arrow key navigation to switch views.

I want to implement this navigation using swipe for touch devices. I tried jGestures library but it doesn't go well with swipe. I have been recommended NOT to use jquery mobile.

Is there any other way to implement swipe?

EDIT: It does not detect swipe cleanly. I tested it on multiple devices, including iPad and it takes multiple swipes to do an action(routing in my case).

This question is related to javascript mobile touch swipe gestures

The answer is


There is also an AngularJS module called angular-gestures which is based on hammer.js: https://github.com/wzr1337/angular-gestures


Have you tried Hammerjs? It supports swipe gestures by using the velocity of the touch. http://eightmedia.github.com/hammer.js/


I made this function for my needs.

Feel free to use it. Works great on mobile devices.

function detectswipe(el,func) {
  swipe_det = new Object();
  swipe_det.sX = 0; swipe_det.sY = 0; swipe_det.eX = 0; swipe_det.eY = 0;
  var min_x = 30;  //min x swipe for horizontal swipe
  var max_x = 30;  //max x difference for vertical swipe
  var min_y = 50;  //min y swipe for vertical swipe
  var max_y = 60;  //max y difference for horizontal swipe
  var direc = "";
  ele = document.getElementById(el);
  ele.addEventListener('touchstart',function(e){
    var t = e.touches[0];
    swipe_det.sX = t.screenX; 
    swipe_det.sY = t.screenY;
  },false);
  ele.addEventListener('touchmove',function(e){
    e.preventDefault();
    var t = e.touches[0];
    swipe_det.eX = t.screenX; 
    swipe_det.eY = t.screenY;    
  },false);
  ele.addEventListener('touchend',function(e){
    //horizontal detection
    if ((((swipe_det.eX - min_x > swipe_det.sX) || (swipe_det.eX + min_x < swipe_det.sX)) && ((swipe_det.eY < swipe_det.sY + max_y) && (swipe_det.sY > swipe_det.eY - max_y) && (swipe_det.eX > 0)))) {
      if(swipe_det.eX > swipe_det.sX) direc = "r";
      else direc = "l";
    }
    //vertical detection
    else if ((((swipe_det.eY - min_y > swipe_det.sY) || (swipe_det.eY + min_y < swipe_det.sY)) && ((swipe_det.eX < swipe_det.sX + max_x) && (swipe_det.sX > swipe_det.eX - max_x) && (swipe_det.eY > 0)))) {
      if(swipe_det.eY > swipe_det.sY) direc = "d";
      else direc = "u";
    }

    if (direc != "") {
      if(typeof func == 'function') func(el,direc);
    }
    direc = "";
    swipe_det.sX = 0; swipe_det.sY = 0; swipe_det.eX = 0; swipe_det.eY = 0;
  },false);  
}

function myfunction(el,d) {
  alert("you swiped on element with id '"+el+"' to "+d+" direction");
}

To use the function just use it like

detectswipe('an_element_id',myfunction);

detectswipe('an_other_element_id',my_other_function);

If a swipe is detected the function "myfunction" is called with parameter element-id and "l,r,u,d" (left,right,up,down).

Example: http://jsfiddle.net/rvuayqeo/1/


I (UlysseBN) made a new version of this script based on this one which use more modern JavaScript, it looks like it behaves better on some cases. If you think it should rather be an edit of this answer let me know, if you are the original author and you end up editing, I'll delete my answer.


Shameless plug I know, but you might want to consider a jQuery plugin that I wrote:

https://github.com/benmajor/jQuery-Mobile-Events

It does not require jQuery Mobile, only jQuery.


NOTE: Greatly inspired by EscapeNetscape's answer, I've made an edit of his script using modern javascript in a comment. I made an answer of this due to user interest and a massive 4h jsfiddle.net downtime. I chose not to edit the original answer since it would change everything...


Here is a detectSwipe function, working pretty well (used on one of my websites). I'd suggest you read it before you use it. Feel free to review it/edit the answer.

_x000D_
_x000D_
// usage example_x000D_
detectSwipe('swipeme', (el, dir) => alert(`you swiped on element with id ${el.id} to ${dir} direction`))_x000D_
_x000D_
// source code_x000D_
_x000D_
// Tune deltaMin according to your needs. Near 0 it will almost_x000D_
// always trigger, with a big value it can never trigger._x000D_
function detectSwipe(id, func, deltaMin = 90) {_x000D_
  const swipe_det = {_x000D_
    sX: 0,_x000D_
    sY: 0,_x000D_
    eX: 0,_x000D_
    eY: 0_x000D_
  }_x000D_
  // Directions enumeration_x000D_
  const directions = Object.freeze({_x000D_
    UP: 'up',_x000D_
    DOWN: 'down',_x000D_
    RIGHT: 'right',_x000D_
    LEFT: 'left'_x000D_
  })_x000D_
  let direction = null_x000D_
  const el = document.getElementById(id)_x000D_
  el.addEventListener('touchstart', function(e) {_x000D_
    const t = e.touches[0]_x000D_
    swipe_det.sX = t.screenX_x000D_
    swipe_det.sY = t.screenY_x000D_
  }, false)_x000D_
  el.addEventListener('touchmove', function(e) {_x000D_
    // Prevent default will stop user from scrolling, use with care_x000D_
    // e.preventDefault();_x000D_
    const t = e.touches[0]_x000D_
    swipe_det.eX = t.screenX_x000D_
    swipe_det.eY = t.screenY_x000D_
  }, false)_x000D_
  el.addEventListener('touchend', function(e) {_x000D_
    const deltaX = swipe_det.eX - swipe_det.sX_x000D_
    const deltaY = swipe_det.eY - swipe_det.sY_x000D_
    // Min swipe distance, you could use absolute value rather_x000D_
    // than square. It just felt better for personnal use_x000D_
    if (deltaX ** 2 + deltaY ** 2 < deltaMin ** 2) return_x000D_
    // horizontal_x000D_
    if (deltaY === 0 || Math.abs(deltaX / deltaY) > 1)_x000D_
      direction = deltaX > 0 ? directions.RIGHT : directions.LEFT_x000D_
    else // vertical_x000D_
      direction = deltaY > 0 ? directions.UP : directions.DOWN_x000D_
_x000D_
    if (direction && typeof func === 'function') func(el, direction)_x000D_
_x000D_
    direction = null_x000D_
  }, false)_x000D_
}
_x000D_
#swipeme {_x000D_
  width: 100%;_x000D_
  height: 100%;_x000D_
  background-color: orange;_x000D_
  color: black;_x000D_
  text-align: center;_x000D_
  padding-top: 20%;_x000D_
  padding-bottom: 20%;_x000D_
}
_x000D_
<div id='swipeme'>_x000D_
  swipe me_x000D_
</div>
_x000D_
_x000D_
_x000D_


I looked at several solutions but all failed with scroll and select text being the biggest confusion. Instead of scrolling right I was closing boxes and such.

I just finished my implementation that does it all for me.

https://github.com/webdevelopers-eu/jquery-dna-gestures

It is MIT so do what you want - and yes, it is really simple - 800 bytes minified. You can check it out on my (under-development) site https://cyrex.tech - swiperight on touch-devices should dismiss popup windows.


Hammer time!

I have used Hammer JS and it work with gesture. Read details from here: https://hammerjs.github.io/

Good thing that it is much more light weight and fast then jQuery mobile. You can test it on their website as well.


I like your solution and implemented it on my site - however, with some little improvements. Just wanted to share my code:

function detectSwipe(id, f) {
    var detect = {
        startX: 0,
        startY: 0,
        endX: 0,
        endY: 0,
        minX: 30,   // min X swipe for horizontal swipe
        maxX: 30,   // max X difference for vertical swipe
        minY: 50,   // min Y swipe for vertial swipe
        maxY: 60    // max Y difference for horizontal swipe
    },
        direction = null,
        element = document.getElementById(id);

    element.addEventListener('touchstart', function (event) {
        var touch = event.touches[0];
        detect.startX = touch.screenX;
        detect.startY = touch.screenY;
    });

    element.addEventListener('touchmove', function (event) {
        event.preventDefault();
        var touch = event.touches[0];
        detect.endX = touch.screenX;
        detect.endY = touch.screenY;
    });

    element.addEventListener('touchend', function (event) {
        if (
            // Horizontal move.
            (Math.abs(detect.endX - detect.startX) > detect.minX)
                && (Math.abs(detect.endY - detect.startY) < detect.maxY)
        ) {
            direction = (detect.endX > detect.startX) ? 'right' : 'left';
        } else if (
            // Vertical move.
            (Math.abs(detect.endY - detect.startY) > detect.minY)
                && (Math.abs(detect.endX - detect.startX) < detect.maxX)
        ) {
            direction = (detect.endY > detect.startY) ? 'down' : 'up';
        }

        if ((direction !== null) && (typeof f === 'function')) {
            f(element, direction);
        }
    });
}

Use it like:

detectSwipe('an_element_id', myfunction);

Or

detectSwipe('another_element_id', my_other_function);

If a swipe is detected the function myfunction is called with parameter element-id and 'left', 'right', 'up' oder 'down'.


The simplest solution I've found that doesn't require a plugin:

document.addEventListener('touchstart', handleTouchStart, false);        
document.addEventListener('touchmove', handleTouchMove, false);
var xDown = null;                                                        
var yDown = null;  

function handleTouchStart(evt) {                                         
    xDown = evt.touches[0].clientX;                                      
    yDown = evt.touches[0].clientY;                                      
}; 

function handleTouchMove(evt) {
    if ( ! xDown || ! yDown ) {
        return;
    }
    var xUp = evt.touches[0].clientX;                                    
    var yUp = evt.touches[0].clientY;
    var xDiff = xDown - xUp;
    var yDiff = yDown - yUp;

    if ( Math.abs( xDiff ) > Math.abs( yDiff ) ) {/*most significant*/
        if ( xDiff > 0 ) {
        /* left swipe */ 
        } else {
        /* right swipe */
        }                       
    } else {
        if ( yDiff > 0 ) {
        /* up swipe */ 
        } else { 
        /* down swipe */
        }                                                                 
    }
    /* reset values */
    xDown = null;
    yDown = null;                                             
};

Examples related to javascript

need to add a class to an element How to make a variable accessible outside a function? Hide Signs that Meteor.js was Used How to create a showdown.js markdown extension Please help me convert this script to a simple image slider Highlight Anchor Links when user manually scrolls? Summing radio input values How to execute an action before close metro app WinJS javascript, for loop defines a dynamic variable name Getting all files in directory with ajax

Examples related to mobile

How to center a component in Material-UI and make it responsive? NullPointerException: Attempt to invoke virtual method 'int java.util.ArrayList.size()' on a null object reference Asus Zenfone 5 not detected by computer background: fixed no repeat not working on mobile Check box size change with CSS onClick not working on mobile (touch) Sharing link on WhatsApp from mobile website (not application) for Android Bootstrap 3 Slide in Menu / Navbar on Mobile How to create a link for all mobile devices that opens google maps with a route starting at the current location, destinating a given place? Using form input to access camera and immediately upload photos using web app

Examples related to touch

Consider marking event handler as 'passive' to make the page more responsive Touch move getting stuck Ignored attempt to cancel a touchmove How to remove/ignore :hover css style on touch devices Fix CSS hover on iPhone/iPad/iPod How to prevent sticky hover effects for buttons on touch devices Draw in Canvas by finger, Android Disable scrolling when touch moving certain element How to implement swipe gestures for mobile devices? Prevent Android activity dialog from closing on outside touch Media query to detect if device is touchscreen

Examples related to swipe

How to recognize swipe in all 4 directions Custom edit view in UITableViewCell while swipe left. Objective-C or Swift How to implement swipe gestures for mobile devices? dynamically add and remove view to viewpager Android: How to handle right to left swipe gestures Detect a finger swipe through JavaScript on the iPhone and Android

Examples related to gestures

How to implement swipe gestures for mobile devices?