You may need to tweak the vertical threshold (15) or horizontal threshold (50).
/**
* You can identify a swipe gesture as follows:
* 1. Begin gesture if you receive a touchstart event containing one target touch.
* 2. Abort gesture if, at any time, you receive an event with >1 touches.
* 3. Continue gesture if you receive a touchmove event mostly in the x-direction.
* 4. Abort gesture if you receive a touchmove event mostly the y-direction.
* 5. End gesture if you receive a touchend event.
*
* @author Dave Dunkin
* @copyright public domain
*/
function addSwipeListener(el, listener)
{
var startX;
var dx;
var direction;
function cancelTouch()
{
el.removeEventListener('touchmove', onTouchMove);
el.removeEventListener('touchend', onTouchEnd);
startX = null;
startY = null;
direction = null;
}
function onTouchMove(e)
{
if (e.touches.length > 1)
{
cancelTouch();
}
else
{
dx = e.touches[0].pageX - startX;
var dy = e.touches[0].pageY - startY;
if (direction == null)
{
direction = dx;
e.preventDefault();
}
else if ((direction < 0 && dx > 0) || (direction > 0 && dx < 0) || Math.abs(dy) > 15)
{
cancelTouch();
}
}
}
function onTouchEnd(e)
{
cancelTouch();
if (Math.abs(dx) > 50)
{
listener({ target: el, direction: dx > 0 ? 'right' : 'left' });
}
}
function onTouchStart(e)
{
if (e.touches.length == 1)
{
startX = e.touches[0].pageX;
startY = e.touches[0].pageY;
el.addEventListener('touchmove', onTouchMove, false);
el.addEventListener('touchend', onTouchEnd, false);
}
}
el.addEventListener('touchstart', onTouchStart, false);
}
Use it like this:
addSwipeListener(document.body, function(e) { alert(e.direction); });
8 comments:
Thanks for code.
Hey there, so would this be detecting a swipe on a HTML site on iPhone? I've been trying to track down a way to make a gallery that works like google image results does....?
Nice code, only problem I ran into is there's no easy way to remove the listener. I just rewrote the class a bit to move all the functions and objects outside the main function, so you can remove the listener if you need to.
-andy
Thanks for this, it's nice and simple but works!
One thing though. I have a site where I want the user to be able to swipe left/right to move between articles, but swiping up down should use the default scrolling action. (It's probably easier to see than describe.)
This seems to work fine on an iPad, but on my iPhone 3G the vertical scrolling ends up being very jerky. Something is interrupting the default action from happening, but I can't work out what to tweak to fix this. Any ideas?
I had a similar issue as the other Phil, specific to iOS4 for some reason, but changing the e.preventDefault() in onTouchMove to e.stopPropagation() solved the issue for me.
Thanks for the code!
as doniguan said, you need to remove the listener.
if you want to do this add these two lines immediately after the "listener(...)" line in the OnTouchEnd function.
el.removeEventListener('touchstart', onTouchStart);
addSwipeListener(el, listener);
I think this is what I am looking for, but I'm not sure if I'm implementing it correctly, because I don't get any alert messages when I swipe. How exactly do I go about testing this?
Awesome code! Thank you!
To get this code work properly on subsequent "swipe" events, I had to add this line to cancelTouch()...
dx = null;
...otherwise Safari kept registering swipe events after my initial swipe, when all I was doing was tapping.
Also, if you make the above change, you also have to change onTouchEnd(e)...
function onTouchEnd(e) {
var dir = dx > 0 ? "right" : "left";
var distance = Math.abs(dx);
cancelTouch();
if (distance > horizontalThreshold) {
listener({ target: el, direction: dir});
}
}
Also, add horizontalThreshold and verticalThreshold in the variable-instantiation section:
var verticalThreshold = 15; // pixels?
var horizontalThreshold = 100; // pixels?
Post a Comment