How to implement swipe gestures for mobile devices?
Solution 1:
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.
Solution 2:
Have you tried Hammerjs? It supports swipe gestures by using the velocity of the touch. http://eightmedia.github.com/hammer.js/
Solution 3:
There is also an AngularJS module called angular-gestures which is based on hammer.js: https://github.com/wzr1337/angular-gestures
Solution 4:
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.
Solution 5:
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.
// usage example
detectSwipe('swipeme', (el, dir) => alert(`you swiped on element with id ${el.id} to ${dir} direction`))
// source code
// Tune deltaMin according to your needs. Near 0 it will almost
// always trigger, with a big value it can never trigger.
function detectSwipe(id, func, deltaMin = 90) {
const swipe_det = {
sX: 0,
sY: 0,
eX: 0,
eY: 0
}
// Directions enumeration
const directions = Object.freeze({
UP: 'up',
DOWN: 'down',
RIGHT: 'right',
LEFT: 'left'
})
let direction = null
const el = document.getElementById(id)
el.addEventListener('touchstart', function(e) {
const t = e.touches[0]
swipe_det.sX = t.screenX
swipe_det.sY = t.screenY
}, false)
el.addEventListener('touchmove', function(e) {
// Prevent default will stop user from scrolling, use with care
// e.preventDefault();
const t = e.touches[0]
swipe_det.eX = t.screenX
swipe_det.eY = t.screenY
}, false)
el.addEventListener('touchend', function(e) {
const deltaX = swipe_det.eX - swipe_det.sX
const deltaY = swipe_det.eY - swipe_det.sY
// Min swipe distance, you could use absolute value rather
// than square. It just felt better for personnal use
if (deltaX ** 2 + deltaY ** 2 < deltaMin ** 2) return
// horizontal
if (deltaY === 0 || Math.abs(deltaX / deltaY) > 1)
direction = deltaX > 0 ? directions.RIGHT : directions.LEFT
else // vertical
direction = deltaY > 0 ? directions.UP : directions.DOWN
if (direction && typeof func === 'function') func(el, direction)
direction = null
}, false)
}
#swipeme {
width: 100%;
height: 100%;
background-color: orange;
color: black;
text-align: center;
padding-top: 20%;
padding-bottom: 20%;
}
<div id='swipeme'>
swipe me
</div>