Seems to be a problem with mobile safari / ios webviews.
While scrolling vertically, if your finger drifts left/right, it will trigger pan on elements in the view.
What workarounds exist?
This is the only reference I could find: http://stackoverflow.com/questions/27193953/permit-horizontal-pan-events-only-if-the-gesture-is-not-already-scrolling-vertic
+1, i'm also looking for this.
+1 Working on a solution now. I wonder why the "Lock Axis" property was removed in Hammer 2.x....
Here's the original open ticket: https://github.com/hammerjs/hammer.js/issues/633
You can check the ev.angle on panstart and set a flag when the angle is pointing left or right, then do the pan action on panmove and reset the flag on panend.
Example:
// ...
proto.swipestart = function(ev) {
var angle = Math.abs(ev.angle);
if (angle >= 90 && angle < 150)
return;
if (angle > 30 && angle < 90)
return;
this.moving = true;
// ...
};
proto.swipemove = function(ev) {
if (!this.moving)
return;
// ... change the marginLeft or translate to deltaX position
// ...
};
proto.swipeend = function(ev) {
if (!this.moving)
return;
this.moving = false;
// ...
};
A work around for this is to just store the starting position. Then you can set a threshold for vertical offset from the start position, and check this in your pan handler if its more then your threshold just return.
I'm going to close this as not a bug. If this workaround does not work or if you think there is a bug here please comment and we will reopen
I’m using Hammer in a React component and was able to pull this off this way:
const Hammertime = require('hammerjs');
// Grab a reference to Panel
const panel = this.refs.Panel;
// Create a Hammer manager
const mc = new Hammertime.Manager(panel);
// Create a recognizer
const Pan = new Hammertime.Pan();
// Add the recognizer
mc.add(Pan);
// Subscribe to events:
// If we detect a scroll before a panleft/panright, disable panning
mc.on('panstart', (event) => {
if (event.additionalEvent === 'panup' || event.additionalEvent === 'pandown') {
this.setState({isScrolling: true});
}
});
// Reenable panning
mc.on('panend', () => this.setState({isScrolling: false}));
mc.on('pan', (event) => {
if (!this.state.isScrolling) {
// … do stuff
}
});
This solution is dead simple, but if all you want to do is to not activate a horizontal pan handler if the user is currently scrolling, and not scroll if the user is currently panning, then this worked well for me:
var isScrolling = false;
var galleryHammer = new Hammer(element, {
recognizers: [
[Hammer.Pan, { direction: Hammer.DIRECTION_HORIZONTAL }]
]
});
// Making the event listener passive means we don't get any delays between
// the user scrolling and the browser having checked if it should prevent
// that event
window.addEventListener('scroll', function() {
isScrolling = true;
}, { passive: true });
window.addEventListener('touchend', function() {
isScrolling = false;
});
galleryHammer.on('pan', function(event) {
if (isScrolling) {
return;
}
// Normal logic...
});
Any valid solution for this
+1, i'm also looking for this.
This worked for me (the code comes from a class, and this.hm is simply an Hammer instance):
this.hm.on('panleft', function(e){ // ...and same for panright
if(e.pointerType == 'touch' && (Math.abs(e.deltaY) > Math.abs(e.deltaX))){ return false; }
// do stuff
}
Most helpful comment
This solution is dead simple, but if all you want to do is to not activate a horizontal pan handler if the user is currently scrolling, and not scroll if the user is currently panning, then this worked well for me: