Any way to prevent horizontal scrolling triggering swipe back gesture on OS X Lion Safari?

后端 未结 8 1926
南笙
南笙 2021-01-30 04:09

I am working on a UI that uses horizontal scrolling in a div element (using overflow: scroll). I cannot scroll to the left, because it would start the

相关标签:
8条回答
  • 2021-01-30 04:29

    Look into the CSS3 style

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

    This works perfectly for me when the used app is only expected on HTML5 / CSS3 capable browsers.

    0 讨论(0)
  • 2021-01-30 04:32

    Piggy backing off of https://github.com/micho/jQuery.preventMacBackScroll posted by micho I have made this possible in both safari and chrome. Also, I made it work for both left scrolling and right scrolling.

    (Sorry that this is in coffeescript. It wouldn't be hard to translate back into 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()
    
    0 讨论(0)
  • 2021-01-30 04:33

    In order to allow an element (e.g. a <div>) to scroll with a trackpad but prevent the browser from going back to the previous page, you need to prevent the browser's default action.

    You can do this by listening to the mousewheel event on the element. Using the scroll properties of the element and the deltaX/Y properties on the event, you can prevent and stop the default action when it goes below zero or above the width/height.

    You can also use the delta information to manually scroll when you are preventing the whole scroll operation. This allows you to actually get to zero rather than stopping at 10 pixels or something.

    // 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);
    

    This works on Chrome, Safari, and Firefox on Mac. I haven't tested on IE.

    This solution will only affect the element in question and will let the rest of the page behave as normal. So you can use your browser as expected and go back a page, but while inside the element you won't accidentally go back when you didn't mean to.

    0 讨论(0)
  • 2021-01-30 04:38

    I also used jQuery mousewheel, attaching this callback:

    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
    }
    
    0 讨论(0)
  • 2021-01-30 04:39

    Yes, in order to disable default behavior (swipe, pinch etc.) all you have to do is to add:

    event.preventDefault();
    

    In you case simply register touchMove listener and use preventDefault() there (in function "touchmove").

    element.addEventListener("touchmove", touchMove, false);
    
    0 讨论(0)
  • 2021-01-30 04:40

    In modern browsers this should do the trick:

    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)
    

    Side note: Firefox has a handy scrollLeftMax property, but it's not standard, so it's better to calculate it ourselves.

    0 讨论(0)
提交回复
热议问题