【问题标题】:Disable scrolling when touch moving certain element触摸移动某些元素时禁用滚动
【发布时间】:2013-04-27 05:09:26
【问题描述】:

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

我已经在草图中使用了 jquery-mobile vmouse 处理程序,如果这会有所不同的话。

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

【问题讨论】:

  • 很确定它不会以它存在的形式对您有很大帮助,但请查看this question。它处理常规滚动,但也许你可以使用它。

标签: javascript jquery-mobile touch


【解决方案1】:

touch-action CSS 属性设置为none,即使与passive event listeners 一起使用:

touch-action: none;

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

【讨论】:

  • 这似乎也杀死了touchstart 事件,所以如果你想识别触摸事件但不允许滚动,那么它就没有用了。
  • @Badrush -- 你确定吗?我在我自己的“可拖动”组件上使用它,touchstart 触发就好了。
  • 非常适合画布元素(只需将 style="touch-action: none" 放在 html 中)。还有什么比这更简单的!此页面上的其他解决方案对我来说失败了。谢谢!
【解决方案2】:

注意:正如@nevf 在 cmets 中指出的那样,此解决方案可能不再有效(至少在 Chrome 中)due to performance changes。建议使用@JohnWeisz 的answer 也建议使用touch-action

与@Llepwryd 给出的答案类似,我使用了ontouchstartontouchmove 的组合来防止在某个元素上滚动。

照原样取自我的一个项目:

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 年 6 月 18 日在 Android 上的 Chrome 和 iPod Touch 中测试

【讨论】:

  • 这个太棒了!
  • 我发现这可以满足我的需要 $(".carousel").on('touchstart', function (e) { e.preventDefault(); }); 这可以防止在我的旋转木马上上下滚动 :)
  • Chrome 现在会忽略 event.preventDefault() 的触摸事件,所以这不起作用。见:developers.google.com/web/updates/2017/01/…
  • 感谢@nevf,我在我的回答中添加了一条注释,指出了这一点,并参考了 JohnWeisz 的回答,似乎是推荐的方法。很高兴知道我的方法至少持续了几年。 ?
【解决方案3】:

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

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

将该类添加到正文将阻止滚动。

【讨论】:

  • 这在 iphone / ipad 上非常适合我。谢谢!
  • 这个解决方案是最好的。我尝试了接受的一个和投票最多的一个。两者都没有奏效。这个干净轻便。
  • 同意,这个解决方案也最适合我。
  • 当我们不需要滚动但 touch-action: none; 允许滚动在触摸设备中无法滚动时工作;当scrollbar-width 为空时,它是实用的。
【解决方案4】:
document.addEventListener('touchstart', function(e) {e.preventDefault()}, false);
document.addEventListener('touchmove', function(e) {e.preventDefault()}, false);

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

【讨论】:

  • 我曾尝试使用 ontouchmove 进行此操作,它确实禁用了滚动,但我无法恢复。
  • 缺少一件重要的事情:你需要设置{passive: false}document.addEventListener('touchstart', handleEndEventFn, { passive: false });
  • 我发现只是禁用 touchmove 而不是将事件监听器绑定到文档,而是将它直接绑定到 canvas 元素有助于防止在使用画布时滚动,但允许 touchstart 工作,因为我没有不要阻止它。
  • 如何恢复 touchmove?我试着打电话给document.removeEventListener('touchmove', handleFn),但它不起作用。
  • @newman 要成功删除它,您必须拥有与添加它时完全相同的所有参数,包括 {passive: false }
【解决方案5】:

最终的解决方案是在document.documentElement 上设置overflow: hidden;,如下所示:

/* 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> 可以用来做一些造型,而且它可以让孩子们表现出意外。

编辑: 关于touch-action: none; - Safari 不支持它according to MDN

【讨论】:

  • 这在 iPad (iOS 13) 上对我有用,我一次只希望一个项目可以移动。 e.preventDefault();似乎并没有阻止屏幕移动。
【解决方案6】:

令我惊讶的是,“preventDefault()”方法在 iOS 13.7 上的最新 Google Chrome(版本 85)上为我工作。它也适用于同一设备上的 Safari,也适用于我的 Android 8.0 平板电脑。 我目前在我的网站上为 2D 视图实现了它: https://papercraft-maker.com

【讨论】:

    【解决方案7】:

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

    你试过了吗?我很想知道这是否可行。

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

    【讨论】:

    • 我不清楚如何使用它;这些电话在哪里/何时拨打?完成“触摸”后如何恢复正常滚动(据我所知,touchmove 并未指定触摸的结束,只是触摸中的移动)。
    • 通过将溢出设置回自动来恢复正常滚动。实际上,在这种情况下,您正在移除滚动条,从而移除正文的可滚动性。因此,当您完成不需要的滚动正在影响的手势时,您需要重新启用它。那会是ontouchend吗?
    • 这是我最初的想法,但它不适用于移动设备
    【解决方案8】:

    我发现ev.stopPropagation(); 为我工作。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-01-22
      • 1970-01-01
      • 1970-01-01
      • 2018-11-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多