10

I've been searching for a clear guide on how these events work and now I'm more confused than when I started.

Certain features of my site involve drag-and-drop. Currently mobile devices (or anything without a mouse) are supported by having the user select the item, tap the "move" button, then touch the drop point. While this works quite well (items are on a visible grid), it's not exactly as user-friendly as dragging.

My initial understanding is that, wherever I assign element.onmousedown, element.onmousemove and element.onmouseup I can simply also assign the same handler to element.ontouchstart, element.ontouchmove and element.ontouchend respectively.

However, that leaves the following questions:

  • How do I get the coordinates of the touch point, and what is it relative to?
  • Will the view be panned (the default action of dragging) and if so is that cancellable?
  • How can I avoid interfering with multi-touch actions such as pinching to zoom if one finger happens to be on a draggable element?
Niet the Dark Absol
  • 320,036
  • 81
  • 464
  • 592
  • It's worth noting that there is a very good reason for almost no native support for drag & drop in mobiles: it can interfere with scrolling. So, if you do extend your own persuado drag-and-drop system to mobile devices, then make absolutely certain that there are no scrollbars in the direction that the drag items get dragged. Otherwise, a person may attempt to scroll the page and end up dragging one of your draggables. Or vice-versa. – Jack G Sep 17 '17 at 18:02

3 Answers3

20

The other answers better address the original question, but for posterity who, like me, find this link trying to make an existing click/drag (mouse) function work on touch screens, this is a very bare bones solution.

If you're adding event listeners, you can add a corresponding 'touchstart' line to your 'mousedown' like so:

 document.getElementById('throttle').addEventListener('mousedown', mouseDown, false);
 document.getElementById('throttle').addEventListener('touchstart', mouseDown, false);

Do the same for any mousemove (touchmove) and mouseup (touchend).

Within your functions, when you get the mouse coordinates, use:

  var top = e.clientY || e.targetTouches[0].pageY; //the same syntax for the x value

That way it checks for a mouse click and drag first, then if that's undefined, it looks for a touch interaction.

Like I said, very barebones, but it worked to get me started.

Josiah
  • 3,008
  • 1
  • 34
  • 45
2

You can determine coordinates by measuring device width/height (window.innerHeight/window.innerWidth).

This article is a good starting point for touch events and overriding them: http://www.html5rocks.com/en/mobile/touch/

Multi-touch gestures shouldn't interfere with the draggable elements. You can use conditionals in your event handlers if they are interfering: (event handler) if (event.touches === 1) handle the event

joewright
  • 325
  • 3
  • 7
0

Here is a short summary about differences between mobile and desktop screen coordinates: What is the difference between screenX/Y, clientX/Y and pageX/Y?

And a working example of implementing the touchmove event listener:

 this.canvas.addEventListener("touchmove", function(e) {
        e.preventDefault();
        touchPosition(e);
    }, false);

var getCanvasPos = function(el) {
    var canvas = document.getElementById(el) || this.getCanvas();
    var _x = canvas.offsetLeft;
    var _y = canvas.offsetTop;

    while(canvas = canvas.offsetParent) {
        _x += canvas.offsetLeft - canvas.scrollLeft;
        _y += canvas.offsetTop - canvas.scrollTop;
    }

    return {
        left : _x,
        top : _y
    }
};

var touchPosition = function(e) {
    var mouseX = e.clientX - this.getCanvasPos(e.target).left + window.pageXOffset;
    var mouseY = e.clientY - this.getCanvasPos(e.target).top + window.pageYOffset;
    return {
        x : mouseX,
        y : mouseY
    };
};
Community
  • 1
  • 1
Endre Simo
  • 11,330
  • 2
  • 40
  • 49