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


73

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

我已经使用了jquery-mobile vmouse处理程序作为草图,如果有区别的话。

更新:在iPhone上,如果我选择要在其上绘制草图的画布,或者在绘图之前只是握住手指一点,该页面就不会滚动,这也不是因为我在页面中进行了编码。


2
可以肯定的是,它不会以那里提供的形式帮助您很多,但是请看一下这个问题。它处理常规滚动,但也许您可以使用它。
Kiruse

Answers:


112

touch-action CSS属性设置为none,即使在被动事件侦听器中也可以使用

touch-action: none;

当事件源自元素时,将此属性应用于元素将不会触发默认(滚动)行为。


2
这似乎也会杀死touchstart事件,因此如果您想识别触摸事件但不允许滚动,则无用。
Badrush '17

11
@Badrush-您确定吗?我在自己的“可拖动”组件上使用它,并且touchstart可以正常触发。
约翰·魏茨

2
非常适合用于canvas元素(只需在html中放置style =“ touch-action:none”即可)。有什么可能更简单!此页面上的其他解决方案对我来说失败了。谢谢!
尤里

1
天哪,

45

注意:正如@nevf的评论所指出的,由于性能变化,该解决方案可能不再起作用(至少在Chrome中)。建议使用touch-action@JohnWeisz的答案也建议使用。

类似于@Llepwryd给出了答案,我用的组合ontouchstart,并ontouchmove防止滚动时,它是有一定的元素。

摘自我的一个项目:

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();
    }
});

本质上,我正在做的事情是监听触摸开始,以查看它是否开始于使用jQuery的另一个元素的子元素,.closest并允许在滚动时打开/关闭触摸运动。该e.target指触摸开始始于元素。

您想防止触摸移动事件的默认设置,但是您还需要在触摸事件结束时为此清除标志,否则任何触摸滚动事件都不会起作用。

这可以在没有jQuery的情况下完成,但就我的用法而言,我已经有了jQuery,不需要编写任何代码来查找元素是否具有特定的父级。

截至2013-06-18,已在Android和iPod Touch上的Chrome中进行了测试


这是一个辉煌!
Gjermund Dahl

我发现这可以满足我的需要$(".carousel").on('touchstart', function (e) { e.preventDefault(); });,可防止在旋转木马上上下滚动:)
chris c

2
Chrome现在忽略触摸事件的event.preventDefault(),因此将无法正常工作。请参阅:developers.google.com/web/updates/2017/01/…–
nevf

1
感谢@nevf,我在回答中添加了注释,指出了这一点,并参考了JohnWeisz的回答,似乎是推荐的方法。很高兴知道我的方法至少持续了几年。🙂
Turnerj

24

CSS上有一些“ hack”,它还允许您禁用滚动:

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

在主体上添加该类将防止滚动。


2
这对我在iPhone / iPad上完美工作。谢谢!
TK123 '16

这个解决方案是最好的。我尝试了被接受和投票最多的一个。两者都不起作用。这是干净轻巧的。
Murtaza Munshi

同意,这个解决方案对我也是最好的。
Eurobertics

19
document.addEventListener('touchstart', function(e) {e.preventDefault()}, false);
document.addEventListener('touchmove', function(e) {e.preventDefault()}, false);

这应该可以防止滚动,但也将破坏其他触摸事件,除非您定义自定义的方式来处理它们。


5
我曾使用ontouchmove尝试过此操作,但它确实禁用了滚动,但无法将其恢复。
斯科特·亨特

4
遗漏了一件重要的事情:您需要设置{passive: false} document.addEventListener('touchstart', handleEndEventFn, { passive: false });
dreampulse 17/09/12

我发现只是禁用touchmove而不是将事件侦听器绑定到文档,而是将事件侦听器直接绑定到canvas元素,这有助于防止在使用画布时滚动,但是touchstart由于我没有阻止它而可以工作。
Badrush '17

我该如何恢复触摸移动?我试图打电话给document.removeEventListener('touchmove', handleFn),但是没有用。
纽曼

@newman要成功删除它,您必须具有与添加时完全相同的所有参数,包括{被动:假}
Johncl,

2

最终的解决方案将被设置overflow: hidden;document.documentElement像这样:

/* 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';
});

通过设置 overflow: hidden触摸开始,它使超出窗口的所有内容都隐藏起来,从而消除了滚动任何内容的可用性(没有内容可滚动)。

touchend通过设置overflow为可以释放锁定后auto(默认值)。

这是更好地把这段<html>,因为<body>可能用于做一些样式设计,而且它会使孩子表现出意外的行为。

编辑:关于-Safari根据MDNtouch-action: none;不支持它。


这在iPad(iOS 13)上对我有用,我一次只想移动一件物品。e.preventDefault(); 似乎并不能阻止恐怖分子移动。
JScarry '20

0

尝试在发生触摸事件时不想滚动的东西上隐藏溢出。例如,在开始时将溢出设置为隐藏,然后在结束时将其设置回自动。

你试过了吗?我想知道这是否行得通。

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

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

我不清楚如何使用它。这些电话在哪里/何时发出?完成“触摸”操作后,如何恢复正常的滚动(据我所知,touchmove并不指定触摸的终点,而只是触摸内的移动)。
Scott Hunter

通过将溢出设置回自动可以恢复正常的滚动。实际上,在这种情况下,您要删除滚动条,因此要删除主体的可滚动性。因此,完成不需要的滚动影响的手势后,您将需要重新启用它。那会触及吗?
伍迪

这是我最初的想法,但不适用于移动设备
oldboy


0

令我惊讶的是,“ preventDefault()”方法在iOS 13.7的最新Google Chrome(版本85)上对我有效。它也可以在同一设备上的Safari上运行,也可以在我的Android 8.0平板电脑上运行。我目前在我的网站上将其实现为2D视图:https//papercraft-maker.com

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.