hammerjs / hammer.js

A javascript library for multi-touch gestures :// You can touch this
http://hammerjs.github.io
MIT License
24.11k stars 2.63k forks source link

Vertically scrollable content breaks panning in Chrome 55 (Android and desktop) #1056

Open romannurik opened 7 years ago

romannurik commented 7 years ago

If the hammer'd element has vertically scrollable content, the pan event seems to break (more specifically, event.deltaX has unexpected values). This seems to be broken as of Chrome 55,a affecting both the Android version and reproducible on touch-enabled laptops or with the DevTools touch emulator. This issue could be related to / a duplicate of #1050.

Example specimen: http://codepen.io/anon/pen/oYRQgM

Repro steps:

  1. Pan horizontally in the 'not vertically scrollable' section. Observe that panning works as expected.
  2. Pan horizontally in the 'vertically scrollable' section. Observe that the content jumps around.

Screencap:

hammerjs-scroll-bug

Shuky commented 7 years ago

Apparently new chrome fires touchcancels relentlessly. Was anyone able to find a temporary fix for this issue?

romannurik commented 7 years ago

I ended up just writing my own carousel without Hammer 😕

For anyone interested, here's the code

Shuky commented 7 years ago

It also breaks swiping

kazlauskis commented 7 years ago

I have downgraded to 2.0.6 and it works fine on Chrome (tools+Android)

Shuky commented 7 years ago

I'm still having issues after the downgrade

mscelina commented 7 years ago

I checked it and played a bit with Hammer code. Major change between Chrome 54 and 55 is turning on Pointer Events. Because of this PointerEventInput class is used instead of TouchInput class. When I changed the code to not instantiate PointerEventInput at all it starts to work properly for me on Chrome 55. I didn't test if such change doesn't break IE or Edge.

bbialas commented 7 years ago

+1

Shuky commented 7 years ago

@mscelina you made my day - Thanks! Any fast way to globally do this other than to fork the library? I only found a way to disable it per Hammer instance, and we have a lot of those :\

PrzemekGonera commented 7 years ago

+1

bbialas commented 7 years ago

@Shuky How you disable it ?

Shuky commented 7 years ago

I was in a hurry to fix so I just edited the hammer.js script locally and changed line 384 to be: var SUPPORT_POINTER_EVENTS = false

Solved all my troubles for now, but hoping this can be addressed in the upcoming versions

bbialas commented 7 years ago

Hammer team, any plan to fix it?

cmdickson commented 7 years ago

@bbialas

How you disable it ?

Specifying the inputClass to use worked in my case: let mc = new Hammer(el, { inputClass: Hammer.TouchInput });

Seems to fix up the pen from the original issue as well.

Only works on touch devices now, so depends what support is needed ...

bbialas commented 7 years ago

@cmdickson thanks a lot, works for me since I need only touch devices support! :)

AbuHani commented 7 years ago

@cmdickson Thank you 👍

larssn commented 7 years ago

Based on @cmdickson 's solution, in angular 2+ you wanna do something like this:

import { HammerGestureConfig, HAMMER_GESTURE_CONFIG } from '@angular/platform-browser';

import * as Hammer from 'hammerjs';
import 'hammer-timejs'; // Optional

export class HammerConfig extends HammerGestureConfig {
    overrides = <any>{
        'pinch': { enable: false },
        'rotate': { enable: false },
        'doubletap': { enable: false }
        // ...
    };

    buildHammer(element: HTMLElement) {
        return new Hammer(element, {
            inputClass: Hammer.TouchInput,
            touchAction: 'pan-y'  // If using horizontal gestures - http://hammerjs.github.io/touch-action/
        });
    }
}

and then in your module providers:

import { HAMMER_GESTURE_CONFIG } from '@angular/platform-browser';
import { HammerConfig } from './hammer.config';

@NgModule({
  declarations: [AppComponent],
  providers: [{ provide: HAMMER_GESTURE_CONFIG, useClass: HammerConfig }],
  bootstrap: [AppComponent]
})
export class AppModule { }
tomrainedotcom commented 6 years ago

@larssn Thanks for this worked a charm. I did however add a check in the buildHammer function to see if the UserAgent was Android.

buildHammer(element: HTMLElement) {
    if ( navigator.userAgent.match(/Android/i) ) {
      return new Hammer(element, {
        inputClass: Hammer.TouchInput,
        touchAction: 'pan-y'
      });
    } else {
      return new Hammer(element);
    }
}
hammadaries commented 4 years ago

@larssn Thanks for this worked a charm. I did however add a check in the buildHammer function to see if the UserAgent was Android.

buildHammer(element: HTMLElement) {
    if ( navigator.userAgent.match(/Android/i) ) {
      return new Hammer(element, {
        inputClass: Hammer.TouchInput,
        touchAction: 'pan-y'
      });
    } else {
      return new Hammer(element);
    }
}

Above does not work with MS Edge browser. Pan stops working. Use Hammer.MouseInput which works with all platforms (Chrome, Safari, Edge)

noahsalvi commented 3 years ago
const hammer = new Hammer(input, {
  inputClass: Hammer.TouchMouseInput,
});

This improved solution seems to fix the problem for both touch and mouse devices