I need to detect and react to left/right-swipes, but want to give the user the ability to scroll on the same element, so as long as he moves his finger only left/right with a maximum up/down movement of X pixels, it should not scroll, but when he exceeds X, it should scroll.
So what I did is:
var startX, startY, $this = $(this);
function touchmove(event) {
var touches = event.originalEvent.touches;
if (touches && touches.length) {
var deltaX = touches[0].pageX - startX;
var deltaY = touches[0].pageY - startY;
if (Math.abs(deltaY) > 50) {
$this.html('X: ' + deltaX + '<br> Y: ' + deltaY + '<br>TRUE');
$this.unbind('touchmove', touchmove);
return true;
} else {
$this.html('X: ' + deltaX + '<br> Y: ' + deltaY);
event.preventDefault();
}
}
}
function touchstart(event) {
var touches = event.originalEvent.touches;
if (touches && touches.length) {
startX = touches[0].pageX;
startY = touches[0].pageY;
$this.bind('touchmove', touchmove);
}
//event.preventDefault();
}
But I doesn't restore the ability to scroll in the "if" case...
Thanks for any tips.
I wrote my own touch handler events.maybe this helps you
it checks for:
fast click : 'fc'
swipe left : 'swl'
swipe right : 'swr'
swipe up : 'swu'
swipe down : 'swd'
each check initializes it's correspondent event.but you can scroll and do whatever else you do normally. you just have some new events.
you need swl swr, I aslo suggest to use fc (fastclick) for click events... it's much faster than normal click.
window.onload = function() {
(function(d) {
var
ce = function(e, n) {
var a = document.createEvent("CustomEvent");
a.initCustomEvent(n, true, true, e.target);
e.target.dispatchEvent(a);
a = null;
return false
},
nm = true,
sp = {
x: 0,
y: 0
},
ep = {
x: 0,
y: 0
},
touch = {
touchstart: function(e) {
sp = {
x: e.touches[0].pageX,
y: e.touches[0].pageY
}
},
touchmove: function(e) {
nm = false;
ep = {
x: e.touches[0].pageX,
y: e.touches[0].pageY
}
},
touchend: function(e) {
if (nm) {
ce(e, 'fc')
} else {
var x = ep.x - sp.x,
xr = Math.abs(x),
y = ep.y - sp.y,
yr = Math.abs(y);
if (Math.max(xr, yr) > 20) {
ce(e, (xr > yr ? (x < 0 ? 'swl' : 'swr') : (y < 0 ? 'swu' : 'swd')))
}
};
nm = true
},
touchcancel: function(e) {
nm = false
}
};
for (var a in touch) {
d.addEventListener(a, touch[a], false);
}
})(document);
//EXAMPLE OF USE
var h = function(e) {
console.log(e.type, e)
};
document.body.addEventListener('fc', h, false); // 0-50ms vs 500ms with normal click
document.body.addEventListener('swl', h, false);
document.body.addEventListener('swr', h, false);
document.body.addEventListener('swu', h, false);
document.body.addEventListener('swd', h, false);
}
in this case h is my handler for every type of event and i add the handlers to the body.
for what i understand your question you just have to write
YOURELEMENT.addEventListener('swr',YOURSWIPERIGHTFUNCTION,false);
YOURELEMENT.addEventListener('swl',YOURSWIPELEFTFUNCTION,false);
to handle multiple elements and the same function... just add one handler.
so if you have
<ul id="ul"><li>1</li><li>2</li><li>3</li></ul>
you do:
var deleteli=function(e){
var li=e.target;
console.log('deleting '+li.textContent);
}
document.getElementById('ul').addEventListener('swl',deleteli,false);
same for fc & swr
there is a bug in ios: don't use alert() .. it will execute 2 times.
There is a "bug" in the accepted answer. If you don't use Chrome on Android but the build in browser or a "webview" (For a html5-hybrid-app) for example, then the swipe is not being detected.
I found out that the event doesn't fire, because of the normal scroll behavior. So adding "e.preventDefault();" in touchmove would fix it or the fix from Eric Fuller in the accepted answer.
It's a nice snipped but in a mobile WebApp or Website this could result in a bad scroll stuttering, because the touch-events are observed the whole time.
So I decided to build something new. It's not as comfortable like to have new event listeners, but it's comfortable enough for my needs and it's performat.
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 = 20; //min x swipe for horizontal swipe
var max_x = 40; //max x difference for vertical swipe
var min_y = 40; //min y swipe for vertical swipe
var max_y = 50; //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)))) {
if(swipe_det.eX > swipe_det.sX) direc = "r";
else direc = "l";
}
//vertical detection
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)))) {
if(swipe_det.eY > swipe_det.sY) direc = "d";
else direc = "u";
}
if (direc != "") {
if(typeof func == 'function') func(el,direc);
}
direc = "";
},false);
}
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/
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With