Draggable is blocking touch event

2019-03-31 19:22发布

问题:

I'm attempting to use drag to move a div back and forth. This part works fine until the div has scrollable content. This isn't a problem on a desktop because of the scrollbar, but a problem occurs on touch devices. Because the touch event is conflicting with the drag event, I'm unable to scroll the content. I tried to create a condition to detect if the drag was more horizontal than vertical..

My hope was to prevent the dragging during a vertical touch interaction, but the UI drag method still fires and overrides the touch event. I'm using the touch-punch plugin to make the draggable work on touch devices, so maybe something in there has complicated the situation. It would be great if I could prevent the UI drag method from firing altogether until the horizontal drag condition is met. I think this would eliminate the interference.

// note the condition inside the drag function
      start: function(e){

        // get starting point of the drag
        startDragX = e.pageX;
        startDragY = e.pageY;
      },
      drag: function(e, ui){

        // prevent drag until user has moved 30px horizontally
        if (Math.abs(e.pageX - startDragX) < 30){
          ui.position.left = 0;
        } else {
          if (ui.position.left < 0) {

            // left drag
            ui.position.left = ui.position.left + 30;
          } else {
            // right drag
            ui.position.left = ui.position.left - 30;
          }
        }
      }

Here is a fiddle to demonstrate the problem (test on touch device): http://jsfiddle.net/jTMxS/2/

回答1:

I had the exact same problem and after a lot of goggling I found a solution in here:

Drag & Drop on IPad Web App - while remaining Scroll functionality

so have a look at the correct answer there and at the piece of code they mentioned (which is actually in other question). I did remove the event.preventDefault() line because in my case I didn't want to lose the scrolling behaviour. Hope this helps.

EDIT I'll include here the details of my solution, as per Chris' comments. I replaced the touch punch plugin for these two functions:

var init = function() {
    document.addEventListener('touchstart', handler, true);
    document.addEventListener('touchmove', handler, true);
    document.addEventListener('touchend', handler, true);
    document.addEventListener('touchcancel', handler, true);        
};

var handler = function(event) {
    var touch = event.changedTouches[0],
        simulatedEvent = document.createEvent('MouseEvent');

    simulatedEvent.initMouseEvent(
         { touchstart: 'mousedown', touchmove: 'mousemove', touchend: 'mouseup' } [event.type],
         true, true, window, 1, 
         touch.screenX, touch.screenY, touch.clientX, touch.clientY,
         false, false, false, false, 0, null);

    touch.target.dispatchEvent(simulatedEvent);
};

The init function needs to be called when document ready.



回答2:

Have you tried this?

(element).ontouchstart = function(e){ 
    e.preventDefault(); 
}

I have used the above to prevent overall scrolling on a web app using touch.

Or you could bind the drag to another gesture, like 2 finger etc using Kuo.js, hammer.js, etc.