当触摸移动某些元素时禁用滚动

我有一个页面,其中有一个部分可以画草图。但是触摸事件,至少是垂直的事件,在移动浏览器上使用时也会滚动页面(这会降低草图体验)。有没有一种方法可以(a)禁用和重新启用页面的滚动(这样我可以在每行开始时关闭它,但在每行完成后重新打开它) ,或者(b)禁用默认的触摸事件处理(可能还有滚动) ,这些事件会进入草图绘制的画布(我不能完全禁用它们,因为草图使用它们) ?

我使用了 jquery-mobile vMouse 处理程序来完成草图,如果这有什么不同的话。

更新 : 在 iPhone 上,如果我选择要绘制的画布,或者只是在绘制之前握住手指一会儿,页面就不会滚动,并不是因为我在页面中编写了什么代码。

151454 次浏览
document.addEventListener('touchstart', function(e) {e.preventDefault()}, false);
document.addEventListener('touchmove', function(e) {e.preventDefault()}, false);

This should prevent scrolling, but it will also break other touch events unless you define a custom way to handle them.

try overflow hidden on the thing you don't want to scroll while touch event is happening. e.g set overflow hidden on Start and set it back to auto on end.

Did you try it ? I'd be interested to know if this would work.

document.addEventListener('ontouchstart', function(e) {
document.body.style.overflow = "hidden";
}, false);


document.addEventListener('ontouchmove', function(e) {
document.body.style.overflow = "auto";
}, false);

Note: As pointed out in the comments by @nevf, this solution may no longer work (at least in Chrome) due to performance changes. The recommendation is to use touch-action which is also suggested by @JohnWeisz's answer.

Similar to the answer given by @Llepwryd, I used a combination of ontouchstart and ontouchmove to prevent scrolling when it is on a certain element.

Taken as-is from a project of mine:

window.blockMenuHeaderScroll = false;
$(window).on('touchstart', function(e)
{
if ($(e.target).closest('#mobileMenuHeader').length == 1)
{
blockMenuHeaderScroll = true;
}
});
$(window).on('touchend', function()
{
blockMenuHeaderScroll = false;
});
$(window).on('touchmove', function(e)
{
if (blockMenuHeaderScroll)
{
e.preventDefault();
}
});

Essentially, what I am doing is listening on the touch start to see whether it begins on an element that is a child of another using jQuery .closest and allowing that to turn on/off the touch movement doing scrolling. The e.target refers to the element that the touch start begins with.

You want to prevent the default on the touch move event however you also need to clear your flag for this at the end of the touch event otherwise no touch scroll events will work.

This can be accomplished without jQuery however for my usage, I already had jQuery and didn't need to code something up to find whether the element has a particular parent.

Tested in Chrome on Android and an iPod Touch as of 2013-06-18

There is a little "hack" on CSS that also allows you to disable scrolling:

.lock-screen {
height: 100%;
overflow: hidden;
width: 100%;
position: fixed;
}

Adding that class to the body will prevent scrolling.

Set the touch-action CSS property to none, which works even with passive event listeners:

touch-action: none;

Applying this property to an element will not trigger the default (scroll) behavior when the event is originating from that element.

The ultimate solution would be setting overflow: hidden; on document.documentElement like so:

/* element is an HTML element You want catch the touch */
element.addEventListener('touchstart', function(e) {
document.documentElement.style.overflow = 'hidden';
});


document.addEventListener('touchend', function(e) {
document.documentElement.style.overflow = 'auto';
});

By setting overflow: hidden on start of touch it makes everything exceeding window hidden thus removing availability to scroll anything (no content to scroll).

After touchend the lock can be freed by setting overflow to auto (the default value).

It is better to append this to <html> because <body> may be used to do some styling, plus it can make children behave unexpectedly.

EDIT: About touch-action: none; - Safari doesn't support it according to MDN.

I found that ev.stopPropagation(); worked for me.

To my surprise, the "preventDefault()" method is working for me on latest Google Chrome (version 85) on iOS 13.7. It also works on Safari on the same device and also working on my Android 8.0 tablet. I am currently implemented it for 2D view on my site here: https://papercraft-maker.com

this worked for me on iphone

$(".owl-carousel").on('touchstart', function (e) {
e.preventDefault();
});

the modern way (2022) of doing this is using pointer events as outlined here in the mozilla docs: https://developer.mozilla.org/en-US/docs/Web/API/Pointer_events

Pointer events build on touchstart and other touch events and actually stop scroll events by default along with other improvements.