0

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);
Anthony Mills
  • 8,676
  • 4
  • 32
  • 51
  • Convert the `pointermove` event listener to `mousedown` which is recognized by all browsers. Then make it so that a `class` is added to the `div` on mousedown. Then invoke a `while` statement of which the condition will be while the mouse is down. Lastly, when the `mouseup` event is triggered, remove the custom class and stop the `while` loop. The gist is to create a specific condition for when the `div` is supposed to move, and abide by it. – Alexander Dixon May 13 '16 at 20:31
  • I'm using the PEP polyfill to allow other browsers to use pointer events. It seemed overly-complex to add the polyfill to the question and demonstration pages, though. – Anthony Mills May 13 '16 at 20:43
  • For PEP to function you will need to use the HTML attributes `touch-action="none"` on the element. – Marius May 13 '16 at 22:06

1 Answers1

4

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>
...
Marius
  • 893
  • 1
  • 8
  • 12