Hammer.js: swipe conflict with pinch

Created on 13 Nov 2015  路  9Comments  路  Source: hammerjs/hammer.js

I am using the hammerjs swipe event and get problems in combination with native zoom (pinch).

In a web application I allow users to scroll:

<meta name="viewport" content="width=device-width, initial-scale=1" />

And navigate with AJAX through my pages on swipe:

var $body = $("body");
var bodyHammer = new Hammer($body[0]);
bodyHammer.on("swipe", function(event){
    // my logic ...
});

However, this causes a usability issue. When users try to zoom-in on e.g. iPads, they don't want to trigger the swipe. Instead they just want to zoom the page. But unfortunately this often causes a swipe to get triggered, especially if you zoom-in horizontally.

Firstly I thought using the pointers option with the value 1 like described in the doc would solve the problem, but it doesn't. I didn't understand why swipe was getting triggered even when swiping with two fingers (if set the pointers value to 1).
Then I thought setting a flag on pinch could solve my issue. So I tried setting:

var $body = $("body");
var bodyHammer = new Hammer($body[0]);
var isPinching = false;
bodyHammer.on("pinchstart", function(event){
    isPinching = true;
});
bodyHammer.on("pinchend", function(event){
    isPinching = false;
});
bodyHammer.on("swipe", function(event){
    if(isPinching){
        return;
    }
    // my logic ...
});

After finding out that I need to enable the pinch event (https://github.com/hammerjs/hammer.js/issues/870) that worked for me. But this caused the side-effect that I wasn't able to scroll down the page (https://github.com/hammerjs/hammer.js/issues/691). But thanks to the idea of @lostPixels I was able to solve the problem with yet another idea:

var $body = $("body");
var bodyHammer = new Hammer($body[0]);
var touchFingers = 1;
$body.on("touchstart", function(event){
    touchFingers = event.originalEvent.touches.length;
});
bodyHammer.on("swipe", function(event){
    if(touchFingers > 1){
        return;
    }
    // my logic ...
});

Now you could ask yourself:

Ok if you have solved the issue why are you fucking open another issue and wasting my time?

Yup :bowtie:

Because:

  1. I want to bring up the question why a swipe-event is getting fired when using the option pointers with value 1 and swiping with two fingers?
  2. If 1. is not a bug, I want to share my use case and fix for others experiencing the same issue and maybe initiate a fix to support native zoom (like on the iPad).

Cheers.

bug

Most helpful comment

I solved this issue by blocking pan / swipe for a certain time (300ms) after / during pinch:

During any pinch event, I do

  lastPinchTime = Date.now();

During pan / swipe, I do:

 if (Date.now()-lastPinchTime < 300) {
       console.log("Ignored pan after pinch!");
       break; // or return
 }

Works perfectly for me. But of cause, this should be part of the library.

All 9 comments

This is the same bug as in #859 #769 and #811

I am sorry but I can't see any same bugs in this issues. Could you please explain what bug you are talking about?
If there are these three closed issues that may be related, why is this issue still present?

None of those three is closed, they are all open and actively being worked on. The issue is that event.pointers.length never gets reduced when a pointer is removed from the screen.

I've missread this. You are right, they're all open.
Even if this is the same bug, I still hope that someone is experiencing the same issue and this workaround helped anyway. :sunglasses:

Hello,

I have a problem on my galaxy S4 Android device: touchstart never fires.
Do you know why?

Is there another solution possible without touchstart event?

Thank You

@bikb Do you have any keyboard connected?
I had such an issue on a Windows 10 tablet with MS Edge. I couldn't solve it, so I supported mouse events too.

No I don't have.

Reopening this as it's representative of an issue we may still have and need to fix in 2.1

I solved this issue by blocking pan / swipe for a certain time (300ms) after / during pinch:

During any pinch event, I do

  lastPinchTime = Date.now();

During pan / swipe, I do:

 if (Date.now()-lastPinchTime < 300) {
       console.log("Ignored pan after pinch!");
       break; // or return
 }

Works perfectly for me. But of cause, this should be part of the library.

Was this page helpful?
0 / 5 - 0 ratings