【问题标题】:Any way to prevent horizontal scrolling triggering swipe back gesture on OS X Lion Safari?有什么方法可以防止水平滚动触发 OS X Lion Safari 上的向后滑动手势?
【发布时间】:2012-01-05 04:36:42
【问题描述】:

我正在开发一个在 div 元素中使用水平滚动的 UI(使用 overflow: scroll)。我无法向左滚动,因为它会启动动画以返回历史。同样,当有一个网站可以前进时,我无法向右滚动。

它在其他浏览器上运行良好,包括 OS X Lion 上的 Chrome,它还支持滑动回到历史。 (在我开发的时候,在 div 中滚动也适用于 Safari。我添加了可能会破坏滚动的事件处理程序和 html,但我不知道是什么让它发生了变化。)

理想情况下,我希望在滚动特定的div 时防止在历史记录中返回或前进(即使它已经结束。)

更新:我尝试添加 jQuery.mousewheel 并以某种方式解决了问题。 (我刚刚在.mousewheel() 上附加了一个空事件处理程序。)我仍在寻找明确的答案。

【问题讨论】:

  • 作为 Lion 用户 - 请不要这样做 - 当你的小网站覆盖我的操作系统设置时,这很烦人!
  • @RichBradshaw 作为狮子用户,当我们的操作系统从根本上改变了互联网的事件模型时,与其他人打交道不想考虑“这个小众计算机操作系统如何从根本上改变事件型号”。\
  • 说实话,我真的是在扮演魔鬼代言人——但值得考虑。我不确定大多数人是否知道您可以横向滚动 - 在大多数人的计算机上,他们仍然有一个带滚轮的鼠标。网站设计是否值得追求,值得仔细考虑。
  • @RichBradshaw 感谢您体贴的 cmets。水平滚动只是我正在处理的 UI 的一个方面。作为 Lion 用户,我对使用水平滚动的网站感到恼火,因为我会不小心回到历史。我认为在预计滚动将以另一种方式工作的小部分禁用它是一个很好的折衷方案。
  • 有人知道如何关闭向左滑动以在浏览器级别触发吗?很长一段时间以来,我一直喜欢使用两指滑动进行水平滚动,但现在当它还触发后退/前进事件时,这很烦人。在 Safari 偏好设置中的任何地方都看不到它。

标签: javascript macos safari


【解决方案1】:

为了允许元素(例如<div>)使用触控板滚动但阻止浏览器返回上一页,您需要阻止浏览器的默认操作。

您可以通过监听元素上的鼠标滚轮事件来做到这一点。使用元素的滚动属性和事件的 deltaX/Y 属性,您可以在默认操作低于零或高于宽度/高度时阻止和停止默认操作。

当您阻止整个滚动操作时,您还可以使用增量信息手动滚动。这使您可以真正达到零,而不是停在 10 像素或其他地方。

// Add the event listener which gets triggered when using the trackpad 
element.addEventListener('mousewheel', function(event) {
  // We don't want to scroll below zero or above the width and height 
  var maxX = this.scrollWidth - this.offsetWidth;
  var maxY = this.scrollHeight - this.offsetHeight;

  // If this event looks like it will scroll beyond the bounds of the element, prevent it and set the scroll to the boundary manually 
  if (this.scrollLeft + event.deltaX < 0 || 
     this.scrollLeft + event.deltaX > maxX || 
     this.scrollTop + event.deltaY < 0 || 
     this.scrollTop + event.deltaY > maxY) {

    event.preventDefault();

    // Manually set the scroll to the boundary
    this.scrollLeft = Math.max(0, Math.min(maxX, this.scrollLeft + event.deltaX));
    this.scrollTop = Math.max(0, Math.min(maxY, this.scrollTop + event.deltaY));
  }
}, false);

这适用于 Mac 上的 Chrome、Safari 和 Firefox。我没有在 IE 上测试过。

此解决方案只会影响相关元素,并让页面的其余部分正常运行。因此,您可以按预期使用浏览器并返回页面,但在元素内部时,您不会意外返回。

【讨论】:

  • 在修复了这段代码中的两个错误后,我测试了它,它不起作用。 Chrome 54、macOS 10.12.1
【解决方案2】:

我这几天一直在寻找解决方案。到目前为止我所拥有的是这个插件:

https://github.com/micho/jQuery.preventMacBackScroll

当您向左和向上滚动时,它禁用了 OSX Chrome 的滚动(我找不到为 OSX Safari 禁用它的方法)。

我希望对您有所帮助,如果您发现任何错误,或者如果您找到一种方法来禁用 Safari 的这种烦人行为,请为该项目做出贡献

【讨论】:

  • 对于寻找 POJS 解决方案的任何人,此插件仅执行以下其他答案中概述的操作:它检查滚动增量是否低于 0,如果是,则调用事件的 preventDefault 方法。
  • 我反对在不需要 jQuery 的地方使用 jQuery。
  • ^ 就像老师因为你没有使用他解决问题的方法而给你差分一样。
  • 我明确赞成覆盖@DiligentKeyPresser 的反对票。发帖人没有要求香草 js 解决方案。我感谢 micho 为开发解决方案所做的努力,并将其发布在此处以供大家受益。
【解决方案3】:

是的,为了禁用默认行为(滑动、捏合等),您只需添加:

event.preventDefault();

在你的情况下,只需注册 touchMove 监听器并在那里使用 preventDefault() (在函数“touchmove”中)。

element.addEventListener("touchmove", touchMove, false);

【讨论】:

  • 抱歉,我不能接受这个作为答案,因为它具有误导性。问题是关于mousewheel 事件。 event.preventDefault() 也是一个 jQuery 方法。
  • 没问题 :) 也许其他人会从这个答案中受益。这不是 jQuery 唯一的方法 developer.mozilla.org/en/DOM/event.preventDefault>。使用它,您可以禁用任何事件的默认行为,而不仅仅是我示例中的 touchmove。你试过了吗?
  • 哎呀,你是对的。对事件对象的快速检查没有将preventDefault 显示为属性,所以我将其关闭。我也不确定,但touchmove 不是特定于触摸屏设备吗?
  • 另外,在这一点上,我很确定这只是 Safari 中的一个错误,因为我无法可靠地重现我原来问题中的情况。
【解决方案4】:

在现代浏览器中,这应该可以解决问题:

element.addEventListener("wheel", function(event) {
  if (Math.abs(event.deltaX) < Math.abs(event.deltaY)) {
    // Scrolling more vertically than horizontally. Let it be!
    return
  }
  const scrollLeftMax = this.scrollWidth - this.offsetWidth
  if (
    this.scrollLeft + event.deltaX < 0 ||
    this.scrollLeft + event.deltaX > scrollLeftMax
  ) { 
    event.preventDefault()
  }
}, false)

旁注:Firefox 有一个handy scrollLeftMax property, but it's not standard,所以最好自己计算。

【讨论】:

  • 泰德,谢谢。这为我节省了很多时间。
【解决方案5】:

查看 CSS3 样式

-ms-touch-action: none;
touch-action: none;

当使用的应用程序仅适用于支持 HTML5/CSS3 的浏览器时,这对我来说非常有效。

【讨论】:

  • @Ciprian - 奇怪,我可以在带有 safari 的旧 iPhone 3GS 和 Moto X 上运行的 android 版本的 safari 上工作。你测试了哪个版本的 safari 浏览器?和设备?我能想到的只是苹果做了一个更新,我没有比 3GS 更新的东西来测试,所以,就是这样 ;)
【解决方案6】:

我还使用了 jQuery 鼠标滚轮,附加了这个回调:

onMousewheel: function(e, delta, deltaX, deltaY){
  e.preventDefault();
  $('leftElement').scrollLeft($('leftElement').scrollLeft() + deltaX); // leftElement =     container element I want to scroll left without going back/forward
  $('downElement').scrollTop($('downElement').scrollTop() - deltaY); // this was another element within the container element
}

【讨论】:

  • 对于未来的读者,mousewheel 已弃用,而推荐使用wheel。 element.addEventListener('wheel', e =&gt; e.preventDefault())
【解决方案7】:

piggy 支持 micho 发布的 https://github.com/micho/jQuery.preventMacBackScroll 我已经在 safari 和 chrome 中实现了这一点。另外,我使它适用于左滚动和右滚动。

(对不起,这是在coffeescript中。翻译回javascript并不难)

$(document).on 'ready', ->

# This code is only valid for Mac
if !navigator.userAgent.match(/Macintosh/)
    return

# Detect browsers
# http://stackoverflow.com/questions/5899783/detect-safari-using-jquery
is_chrome = navigator.userAgent.indexOf('Chrome') > -1
is_safari = navigator.userAgent.indexOf("Safari") > -1
is_firefox = navigator.userAgent.indexOf('Firefox') > -1

# Handle scroll events in Chrome, Safari, and Firefox
if is_chrome || is_safari || is_firefox

    $(window).on 'mousewheel', (event) ->
        dX = event.deltaX || event.originalEvent.deltaX
        dY = event.deltaY || event.originalEvent.deltaY

        # If none of the parents can be scrolled right when we try to scroll right
        prevent_right = dX > 0 && $(event.target)
            .parents().addBack()
                .filter ->
                    return this.scrollWidth - this.clientWidth != 0 &&
                     $(this).scrollLeft() < this.scrollWidth - this.clientWidth &&
                     ($(this).css('overflow-y') == 'scroll' || $(this).css('overflow-y') == 'auto')
                .length == 0

        # If none of the parents can be scrolled left when we try to scroll left
        prevent_left = dX < 0 && $(event.target)
            .parents().addBack()
                .filter ->
                    return $(this).scrollLeft() > 0
                .length == 0

        # If none of the parents can be scrolled up when we try to scroll up
        prevent_up = dY > 0 && !$(event.target)
            .parents().addBack()
                .filter ->
                    return $(this).scrollTop() > 0
                .length == 0

        # Prevent minute left and right scroll from messing up vertical scroll
        if (prevent_right || prevent_left) && Math.abs(dY) > 5 && !prevent_up
            return
        # Prevent futile scroll, which would trigger the Back/Next page event
        if prevent_left || prevent_up || prevent_right
            event.preventDefault()

【讨论】:

    【解决方案8】:

    我是从用户的角度来搜索相同的东西时来到这里的。所以这里是影响这一点的 FF 设置:

    browser.gesture.swipe.left
    browser.gesture.swipe.right
    

    将它们设置为空字符串(删除那里的内容)

    来源:https://forums.macrumors.com/threads/disabling-firefox-back-forward-from-horizontal-scrolling.111589/

    【讨论】:

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