Anthony Mills
Anthony Mills

Reputation: 8784

Supporting dragging and panning in a scrollable div with Pointer Events

Consider the case of a draggable div in a scrollable region. When you touch inside the div, further finger movements should drag the div around the region. When you touch outside the div, further finger movements should pan the scrollable region.

I have a JSFiddle which illustrates this. With the mouse, I can drag the div around easily, but touch events don't seem to work as well.

Note: I'm using pointer events in the fiddle, so if you're using a browser that doesn't support them, it might seem like the fiddle is broken.

Does anyone know how to properly implement this interaction?

http://jsfiddle.net/mrmills/13t34jsv/

HTML:

<div id="scroll-outer">
  <div id="scroll-inner">
    <div id="handle">
    </div>
  </div>
</div>

CSS:

#scroll-outer { width: 400px; height: 400px; overflow: auto }
#scroll-inner { width: 2000px; height: 2000px }
#handle { width: 44px; height: 44px; background-color: rgba(0,0,0,0.5) }

JS:

function pointerDown(ev) {
  scrollInner.addEventListener("pointermove", pointerMove);
  scrollInner.addEventListener("pointerup", pointerUp);

  dragStartX = ev.pageX; dragStartY = ev.pageY;
}

function pointerMove(ev) {
  handle.style.transform = "translate3d(" +
    (x + ev.pageX - dragStartX) + "px, " +
    (y + ev.pageY - dragStartY) + "px, 0)";
}

function pointerUp(ev) {
  scrollInner.removeEventListener("pointermove", pointerMove);
  scrollInner.removeEventListener("pointerup", pointerUp);

  x = x + ev.pageX - dragStartX;
  y = y + ev.pageY - dragStartY;
}

var x = 0;
var y = 0;
var dragStartX = 0;
var dragStartY = 0;

var handle = document.getElementById("handle");
var scrollInner = document.getElementById("scroll-inner");
handle.addEventListener("pointerdown", pointerDown);

Upvotes: 0

Views: 3394

Answers (1)

Marius
Marius

Reputation: 961

To fire pointer events with a touch-based input on an element, you need to set the CSS attribute touch-action: none (default is auto) on that element.

In your case setting touch-action: none on div#handle would make it draggable.


Addition: If you use PEP, you will have to add the HTML data-attribute touch-action="none" to the element, e.g.:

...
<div id="handle" touch-action="none"></div>
...

Upvotes: 4

Related Questions