Interact.js: Suggestion: Add a hint for mobile and draggable to use `touch-action: none;`

Created on 30 Jan 2018  路  8Comments  路  Source: taye/interact.js

Draggable on mobile triggers onend before you let go of your finger. That may happen when the page has scroll and the phone scroll interferes with the item dragging.

To prevent that from happening you need this style on your container

.container {
  touch-action: none;
}

My suggestion is to include this information somewhere in the examples/docs.

I spent quite some time trying to figure out why it wasn't working.

Most helpful comment

THANK YOU for this. Also, a tip for others - it works fine to add this css to whatever is being dragged as opposed to the container:

.draggable {
  touch-action: none;
}

All 8 comments

THANK YOU for this. Also, a tip for others - it works fine to add this css to whatever is being dragged as opposed to the container:

.draggable {
  touch-action: none;
}

It does not still work for Safari

Found this to be an issue after upgrading to 1.3.x from 1.2.7

As for Safari, looks like it doesn't support touch-action:none right now

Any updates on this issue? It definitely makes things a bit difficult when trying to use interactjs on an iOS device. I found that this issue is present when resizing as well.

I did come up with a (somewhat janky) alternate workaround that seems to fix the issue on _both_ iOS and Android- add an event listener for the various touch events, that fire event.preventDefault() and append this to the element using the <event>start callback and remove them from the element using the <event>end callback. For example:

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

// Later in the code

interact(ele).resizable({
  edges: { left: false, right: true, bottom: false, top: false },
})
.on('resizestart', (evt: any) => {
  // nullify touch events.
  ['touchstart', 'touchmove', 'touchend'].forEach((et) => ele.addEventListener(et, ignoreTouch));
})
.on('resizemove', function (event: any) {
  // do stuff while resizing the element
})
.on('resizeend', (evt: any) => {
  // Remove nullify touch events in case we need to use touch events for something else.
  ['touchstart', 'touchmove', 'touchend'].forEach((et) => ele.removeEventListener(et, ignoreTouch));
  // Code to handle the resized element when resizing is complete.
});

Note that you must use a named function (in my case ignoreTouch), if you want to remove those event listeners when you are finished resizing/dragging.

I just used
style="overscroll-behavior: none;touch-action:none;"
on the div container and the reload behavior is stopped in Android and iOS... I still can drag element and the window, but it doesn't reload.
just for info, these are all the css property I used in my case:
style="overscroll-behavior: none;touch-action:none;overflow-x: scroll;overflow-y: hidden;margin: 0;height: 90vh;min-width: 100vw"

Thanks a lot !!

For anyone still struggling with this, I had a horizontal slider which I enabled with draggable.
On mobile I got the buggy behaviour which was fixed by using touch-action: none;.

But this caused the page to be unscrollable on the element with that property, meaning the user could get stuck if that element almost or completely covered the viewport. I solved it by using a combination of the startAxis: 'x' option for draggable and setting touch-action: pan-y; on the element. In this way, the only dragging catched by interact.js would be horizontally and the only scrolling catched by the browser would be vertically.

See: https://developer.mozilla.org/en-US/docs/Web/CSS/touch-action

Where do I need to add touch-action: none? To the element being dragged? To the container? To the body?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

rbozan picture rbozan  路  9Comments

sualko picture sualko  路  9Comments

jbaartman picture jbaartman  路  4Comments

mateop picture mateop  路  7Comments

johannes-z picture johannes-z  路  4Comments