hammerjs / hammer.js

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

How to disable vertical pan scrolling on mobile? #1169

Open choxi opened 6 years ago

choxi commented 6 years ago

On mobile Chrome and Safari, by default the vertical pan gesture is used to scroll the page. When I use Hammer to detect a vertical pan on an object, it works but it also scrolls the page. I've tried calling event.preventDefault() in my panning handler but it doesn't stop the vertical scrolling. I've also tried adding touch-action: none as a CSS attribute to the body of the page but that doesn't appear to disable it either. Is there a way to do this? The vertical pan gesture seems sort of useless if it always scrolls the page.

Edit: I'm able to prevent the vertical pan-to-scroll by adding this before initializing my Hammer code:

document.addEventListener("touchmove", function(event){ event.preventDefault(); });

But then Hammer doesn't pick up these events either (any other direction still works).

rajadain commented 6 years ago

Not sure if this would help your case, but I ran into a similar problem where a certain div would scroll. This was nested inside a larger area with Hammer applied to it, so dragging from the outside would work but the inside would trigger the scroll and break it. Fortunately, it wouldn't break immediately, but after the first couple of events.

I ended up doing something like this:

const isScrollDisabled = false;

function preventDefault(e) {
  e.preventDefault();
}

function panHandler(e) {
  const DOCUMENT_POSITION_CONTAINED_BY = 16;
  const problemDiv = document.getElementById('problem-div');

  if (problemDiv.compareDocumentPosition(e.target) & DOCUMENT_POSITION_CONTAINED_BY) {
    // Dragging within the scrollable problem div
    if (!isScrollDisabled) {
      problemDiv.addEventListener('touchmove', preventDefault);
      isScrollDisabled = true;
    }
  }

  /** Do other panning things **/

  if (e.isFinal) {
    const restoreCondition = true; // In case you want to restore state

    if (restoreCondition) {
      problemDiv.removeEventListener('touchmove', preventDefault);
      isScrollDisabled = false;
    }
  }
}