New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pan event doesn't work correctly with touch-action pan-y in Chrome 55 #1050

Open
zuibunan opened this Issue Nov 28, 2016 · 46 comments

Comments

Projects
None yet
@zuibunan

zuibunan commented Nov 28, 2016

Before upgrade to Chrome 55.0.2883.59 beta (64-bit), it works fine
but now, when I pulldown in chrome emulator , the panmove event just triggered once or twice, and the event data is not correct

image

this is the right event data when i set touchAction none, but if touchAction is none , the page will not scroll

image

coarse demo
http://jsbin.com/tevitozuku/edit?output

@BossLevel

This comment has been minimized.

BossLevel commented Dec 6, 2016

I have a similar problem - panmove has been working for nearly 2 years, no change to the code and it's stopped. This is Chromium Version 55.0.2883.75 (64-bit). The event appears to trigger correctly at first but the event data I am capturing (var x = event.changedPointers[0].movementX * -1;var y = event.changedPointers[0].movementY * -1;) appears as 0 values. The event will then trigger with any mouse move (not pan) over the bound area.

It appears to work fine in Firefox 50.0.2 but there my bound Tap events are now passing incorrect x/y info.

@glomotion

This comment has been minimized.

glomotion commented Dec 8, 2016

I think i too am having this issue after updating to Chrome to Version 55.0.2883.75.

All pan directions are a problem for me right now. PanStart fires as expected, but the onPan event fires once only, for that entire gesture.

*Note, it only seems to be a problem while touch emulation is running. If you disable "touch emulation" then everything works as expected.

My guess is the chrome team changed something in the way that chrome emulates device touch events...

@Makaveli17

This comment has been minimized.

Makaveli17 commented Dec 14, 2016

+1 , I have the same problem on pandown/panup and my panend is never triggered .
:(

@IgorKharkiv

This comment has been minimized.

IgorKharkiv commented Dec 14, 2016

+1 , I have the same problem on pandown/panup and my panend is never triggered .
:(

+1 This is a very big problem =((

@BossLevel

This comment has been minimized.

BossLevel commented Dec 15, 2016

Agreed - I'm going to have to pull hammer out of my project if it remains this way.

@sitexw

This comment has been minimized.

sitexw commented Dec 15, 2016

Ok, I'm not crazy ^^ I have exactly the same problem.
(Except that in my case, I am on the eve of a release in production !)

@arjunkathuria

This comment has been minimized.

Contributor

arjunkathuria commented Dec 15, 2016

looks like chrome team indeed update touch-action options.

they added 'pan-up pan-down pan-left pan-right' with earlier pan-x and pan-y.
link here

they might be interfering with the TOUCH_ACTION constants in hammer.
link here

These properties force the user to start gestures in one direction before the element will respond. This is similar to the "pull-to-refresh" gesture which only responds when the user gestures downwards on the screen.

This line could be the troubling bit.

cc:- @arschmitz

@glomotion

This comment has been minimized.

glomotion commented Dec 16, 2016

So we're also in the unfortunate predicament of being very, very close to a launch. The app concerned is pretty heavily affected by this bug.

Is there any chance at all, we could get some kind of eta on a potential patch? Or even just an indication of how severe this problem really is (and how complicated the fix will need to be) - would be awesome.

I really don't want to have to rip hammer out of the project (hammer rox!) - but may be forced to if this issue remains for much longer. :(

@zuibunan

This comment has been minimized.

zuibunan commented Dec 16, 2016

@glomotion Chrome Dev for Android have the problem too , not only emulator

@glomotion

This comment has been minimized.

glomotion commented Dec 16, 2016

@zuibunan Yup. I'm now finding that too. :( I think it was because the Android devices I was testing on were yet to upgrade to Chrome 55. 55 appears to have since rolled out to all our test devices now - and now they all show this problem.

@raghavendra-polanki

This comment has been minimized.

raghavendra-polanki commented Dec 16, 2016

Any one able to find a solution for this problem?

@gargsahil25

This comment has been minimized.

gargsahil25 commented Dec 16, 2016

Make sure you set the proper touch-action css attribute for your canvas element.
Ref: https://developers.google.com/web/updates/2016/10/touch-action
My issue got resolved by adding below code in my css
.main-canvas { touch-action: none !important; }

@rejhgadellaa

This comment has been minimized.

rejhgadellaa commented Dec 16, 2016

I've done some digging and testing and it looks like the Chrome's new Pointer Events api has some issues:

  • On desktop it fires pointermove after pointerup
  • On mobile (android, at least) the touch-action css property does not get inherited by child elements

That last thing might be the problem if you, like me, attached hammer to an element that has children because the event gets cancelled if you start the touch on a child element (it fires pointerdown, pointermove and then pointercancel).

I've created tickets for the issues above on the chromium tracker so you can star those:
https://goo.gl/esp1S5 and https://goo.gl/LesGXI

@rejhgadellaa

This comment has been minimized.

rejhgadellaa commented Dec 16, 2016

As an addition to @gargsahil25 solution: make sure the touch-action property is set to all child elements as well:
.main-canvas, .main-canvas * { touch-action: none; }

I recommend not using the !important because you may want to override that property for one or more child elements, like..
.main-canvas .cant-touch-this { touch-action: auto; }

Also, using !important is not a good idea in general and should only be used when needed. Or maybe unless gargsahil25 has a very good reason for using that, of course :)

(PS: the above solution is a complete hack/workaround for a bug. the bug needs fixing, this solution needs to go :P)

@antipod

This comment has been minimized.

antipod commented Dec 16, 2016

Thanks @gargsahil25, it worked semi-ok. I have a couple of carousels on the mobile website and this at least made it pan i y-direction as it did before. The only problem is that before Chrome 55 rolled out, I could put my finger on the carousel and scroll up and down on the page, whereas now nothing happens.

Maybe that can be solved with hammer.js itself. If anyone have a clue about how to fix that, I'm listening.

@rejhgadellaa

This comment has been minimized.

rejhgadellaa commented Dec 16, 2016

@antipod You want horizontal carousel but have vertical scroll work?
`touch-action: pan-y;

See hammerjs docs:
http://hammerjs.github.io/touch-action/

And:
https://github.com/hammerjs/hammer.js/wiki/How-to-fix-Chrome-35--and-IE10--scrolling-(touch-action)`

@antipod

This comment has been minimized.

antipod commented Dec 16, 2016

@rejhgadellaa I did try that but it doesn't work completely. I can pan in the x direction, and it will allow me to scroll on the page. BUT, hammer.js registers that vertical scroll as a panleft / panright on the carousel and it bugs like it did before, after Chrome updated to 55. Though it only registers it once. Still, this offsets the carousel. Might be a solution there somewhere... I'll find it.

@rejhgadellaa

This comment has been minimized.

rejhgadellaa commented Dec 16, 2016

@antipod did you also attach touch-action to all the child elements? see my comment above. I have an implementation like that (with pan-y) and it works for me.

@BossLevel

This comment has been minimized.

BossLevel commented Dec 16, 2016

I'm afraid that touch-action on my affected elements didn't solve any of them so sadly it appears to be an incomplete hack.

@runspired

This comment has been minimized.

Contributor

runspired commented Dec 16, 2016

cc @arschmitz I think this is a little out of my knowledge domain at the moment, if there's a new spec to read I'll read it and a link to new APIs is appreciated but sounds like this may also require some spelunking on how the new stuff works?

@hanwiz

This comment has been minimized.

hanwiz commented Dec 20, 2016

When I use v2.04 or the latest version v2.08 Nov, this doesn't allow me to pan or swipe in Chrome 55. However, with v2.08 Apr, distributed version irons out all the bugs I got. So someone like me should use the distributed version first before trying anything else.

Oops, actually without "touch-action: none", it doesn't work in the Chrome debugging mode (touch emulation).

So, you should use both the distributed version v2.08 Apr and touch-action: none.

@BossLevel

This comment has been minimized.

BossLevel commented Dec 21, 2016

Again, using the Apr distributed version (I'm assuming by that you mean the .min.js file) === no dice (I was using that version all along).

Noting that the Hammer home page works fine and demos the functionality that I previously had working with panmove, I had a look at the code. I see there that you use the event.deltaX/Y values where I had been using the event.changedPointers[0].movementX/Y values. However adapting my code to use these did not result in a fix as e.g. changing direction mid-pan is not reflected by these values (as they are deltas).

@runspired & @arschmitz I really apologise for telling you guys what to do, but it strikes me that if the developers of the world's most popular browser decide to alter their internal API and that impinges directly on your maintained project's functionality, then you're going to have to bite the bullet and re-factor. Or be maintainers of an increasingly out-of-date project.

@BossLevel

This comment has been minimized.

BossLevel commented Dec 21, 2016

And if it's any consolation (and I know it isn't) I've had Google do this to me on multiple occasions also :(

@hanwiz

This comment has been minimized.

hanwiz commented Dec 21, 2016

@BossLevel Can you adapt your code something like this? In firefox, two values are the same most of the time except outside the boundaries. Here is my pen http://codepen.io/hanwiz/pen/ObqGEo.

var pY=0;
// listen to events...
mc.on("panleft panright panup pandown tap press", function(ev) {
    myElement.textContent = ev.type +" gesture detected." + ev.changedPointers[0].movementY + " " + (ev.deltaY - pY);
   pY = ev.deltaY;
});
@BossLevel

This comment has been minimized.

BossLevel commented Dec 21, 2016

@hanwiz - thanks for your time and effort - the good news is that with some slight modifications, your code works :)

2 points to make before documenting said modifications:

  1. I had wanted to avoid the use of some "globals" (pY - I know it's not a proper global) as it seemed redundant to have to manage these when Hammer was meant to be doing it for me. However given the ease and speed of implementation utilising these, needs must.
  2. FYI, as per my original post, the ev.changedPointers[0].movementX/movementY values are always zero for me, no matter where and how fast I pan.

With that in mind, line 14 of your pen can be reduced to myElement.textContent = ev.type +" gesture detected." + (ev.deltaY - pY);

In addition, after ending a panmove, the next pan jerks initially. To remove this add the additional following binding:

mc.on('panend', function(event) {
			pX = 0;
			pY = 0;
		});

I still think something needs to be done about this issue (or at least have an example/documentation on the site) but that's your business and I once again thank you for your efforts, particularly @hanwiz

@hrvojekindl

This comment has been minimized.

hrvojekindl commented Dec 28, 2016

Adding the "touch-action: pan-y" to the affected scrollable element (and it's descendants) solved the issue for me. Here's the SASS class that I used:

.scroll-and-swipe {
  overflow-y: scroll;
  touch-action: pan-y !important;
  -webkit-overflow-scrolling: touch;

  & * {
    touch-action: pan-y !important;
  }
}
@glomotion

This comment has been minimized.

glomotion commented Jan 5, 2017

So I'm still having quite a few problems with Hammer.
Even the simplest examples of hammer seem to be broken in Chrome (with touch emulation enabled) atm.
Also, having padding applied to the hammer bound element also seems to cause issues with offset calcs.

http://codepen.io/creative-lab-sydney/pen/ygyMMO

@miksh7

This comment has been minimized.

miksh7 commented Jan 30, 2017

One of the Chromium tickets mentioned above has been fixed
https://bugs.chromium.org/p/chromium/issues/detail?id=161464

Would it fix this issue or the Hammer team should still make a fix?

@Mathews2115

This comment has been minimized.

Mathews2115 commented Feb 12, 2017

@antipod - I noticed on chrome (at least in the touch emulation), that when I get the bogus pan event on vertical scroll, the srcEvent.type is pointercancel.

So a quick ugly work around is to set a panning variable to true on pan-start. But only if the srcEvent.type isnt pointercancel, else, set it to false.

Then on your horizontal pan handler, only if panning is true, do your actual stuff. Otherwise, preventDefault. I haven't fully vetted this out yet but it seems to work initially.

Hope this helps!

@alexanderwiebe

This comment has been minimized.

alexanderwiebe commented Feb 15, 2017

I followed @Mathews2115 steps above and it seems to be working for me. I did not find that the sass rules impacted this.

I made a quick slider with some scrolling to test out in:
Three 'full screen' columns with a footer.

http://codepen.io/alexanderwiebe/pen/qRvbOY

For all events I would wrap existing event code with the following statement:
if(ev.srcEvent.type !== 'pointercancel'){

Are there any other effects of ignoring pointercancel in other browsers ? I haven't found any in quick testing.

@wmertens

This comment has been minimized.

wmertens commented Apr 24, 2017

@Mathews2115 has your workaround been behaving well? Would it be hard to do this in hammerjs itself?

I don't understand how the bogus event comes to be, for me it only happens when I pan across a certain area of my screen…

@Mathews2115

This comment has been minimized.

Mathews2115 commented Apr 24, 2017

@wmertens So far so good on my end.

@blackswanny

This comment has been minimized.

blackswanny commented Jun 1, 2017

fixed with the same
if(ev.srcEvent.type !== 'pointercancel'){
however, 50% of my pans are marked as canceled, which are rejected

@Zenfeder

This comment has been minimized.

Zenfeder commented Jun 15, 2017

@glomotion Thank you very much, it works correctly when i do it as you said.

@MattKunze

This comment has been minimized.

MattKunze commented Jun 22, 2017

@blackswanny - I think I'm seeing similar behavior where many of the pans aren't being recognized right on Android, I made a project to reproduce the issue and #1118 as a simple fix that improves the case I'm running into at least

@web-jenezis

This comment has been minimized.

web-jenezis commented Aug 9, 2017

Got the same issue yesterday during the work with Hammer.js. Here is the solution:

// by default, it only adds horizontal recognizers
var mc = new Hammer(myElement);

// let the pan gesture support all directions.
// this will block the vertical scrolling on a touch-device while on the element
mc.get('pan').set({ direction: Hammer.DIRECTION_ALL });```
@paranoidjk

This comment has been minimized.

paranoidjk commented Sep 5, 2017

same problem here.

@malina-kirn

This comment has been minimized.

malina-kirn commented Oct 26, 2017

@web-jenezis : your solution worked for me. I saw that the pointercancel event type pointed out by @alexanderwiebe was indeed causing the bad deltaX and deltaY values, but as @blackswanny commented, some interactions were nearly all pointercancel events, so discarding them would occasionally cause the pan to be almost completely unresponsive. Setting the pan direction caused the pointercancel events to stop firing altogether.

@blackswanny

This comment has been minimized.

blackswanny commented Oct 26, 2017

@web-jenezis @malina-kirn I used Hammer for React and not sure that directions prop is passed to hammer, cause i still see issues with it


 <Hammer
            direction={Hammer.DIRECTION_ALL}
            onPan={this.onPan}
            onPanEnd={this.onPanEnd}
            onPanStart={this.onPanStart}
            onDoubleTap={this.onDoubleTap}
            options={{
                recognizers: {
                    swipe: {
                        enable: false
                    },
                    pinch: {
                        enable: false
                    },
                    press: {
                        enable: false
                    },
                    pan: {
                        enable: true
                    },
                    tap: {
                        enable: true
                    }
                }
            }}>
@malina-kirn

This comment has been minimized.

malina-kirn commented Oct 26, 2017

@blackswanny : as @web-jenezis pointed out, setting the direction attribute blocks vertical scroll on the element. Perhaps you can block native vertical scroll instead of setting direction? This also seems to work for me:

CSS:

.no-scroll {
  overflow: hidden;
}

Add the no-scroll class to the element you're panning. I'd previously tried this on outer elements (blocking scroll on the entire page), but it seems it must be applied directly to the element being panned. I suspect it would have worked if I'd applied the rule to all child elements.

@garyskiba

This comment has been minimized.

garyskiba commented Nov 29, 2017

add:
delete window.PointerEvent;
in your index.html PRIOR to loading hammer.js, and it will ignore those events.
You can also set SUPPORT_POINTER_EVENTS = false; (line 384 of v2.0.8) to do the same thing.
Ideally the devs would add the ability to turn this off, but so goes the open source dilemma...

@fssrepository

This comment has been minimized.

fssrepository commented Dec 7, 2017

@garyskiba

easier solution if you add the

var SUPPORT_POINTER_EVENTS = false; line at the beginning of your file.

It's dirty but at least don't touch the hammer.js itself

@blackswanny

This comment has been minimized.

blackswanny commented Dec 7, 2017

@fssrepository , according to what i see it's not global var and we can't override it so hammer will pick up another value. But I would rather change this var than override native PointerEvent, cause not like to affect other parts of app

@SelfishLucho

This comment has been minimized.

SelfishLucho commented Dec 7, 2017

@garyskiba @fssrepository Both solutions brakes 'press' if u are unfornate as me if u want to use both 'pan' and 'press' with hammerJS globally available

pirxpilot added a commit to pirxpilot/liftie that referenced this issue Dec 24, 2017

fix swipe action on Chrome
Chrome > 55 implements pointer events but in order for them to work
properly we need to make sure that all children of swipe element have
touch-action property (it is not inherited in chrome)

see:
hammerjs/hammer.js#1050
@simeyla

This comment has been minimized.

simeyla commented Aug 29, 2018

The actual issue described still persists today - not surprising since hammerjs hasn't been updated.

That is the issue of getting wildly odd numbers like

deltaX: -120
deltaY: -118

As others have mentioned, the solution is to use touchAction: 'none' on the thing you're panning. Unfortunately if you want this 'thing' to be scrollable vertically (as part of normal vertical scrolling behavior) you must remove this touchAction - because the browser locks the scrollability when you have it.

I had cases where I wanted to be informed about the attempt of the user to scroll - i didn't really need a delta. I just needed to know which direction it was.

Turns out you can filter out these bizarre numbers with:

filter(e=> e.center.x != 0 && e.center.y != 0)

That leaves you with a few events like e.deltaX = 2, e.deltaY = -11 but that will let you scroll the page and still get an indication of the users intent.

Remember that when you scroll the whole page what do you really expect delta to be? You're moving the whole viewport after all! This at least filters out that awful janky large seemingly random numbers.

Me 36 hours ago: "I'm so excited to finally have time to play with hammerjs, the leading gestures library - and never have to worry about compatibility ever again"
Me now: REDACTED

@marcus13371337

This comment has been minimized.

marcus13371337 commented Sep 24, 2018

On the parent wrapper:
touch-event: none

The element inside the wrapper I wanted to be able to scroll vertically:
touch-event: pan-y

Solved it for me!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment