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 jG
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;
};
There is also an AngularJS module called angular-gestures which is based on hammer.js: https://github.com/wzr1337/angular-gestures
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.
Have you tried Hammerjs? It supports swipe gestures by using the velocity of the touch. http://eightmedia.github.com/hammer.js/
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>