Любой способ предотвратить горизонтальную прокрутку запуска жестом прокрутки назад в OS X Lion Safari? - PullRequest
50 голосов
/ 05 января 2012

Я работаю над пользовательским интерфейсом, который использует горизонтальную прокрутку в элементе div (используя overflow: scroll). Я не могу прокрутить влево, потому что это запустит анимацию для возврата в историю. Кроме того, я не могу прокрутить вправо, когда есть веб-сайт, на который можно перейти.

Хорошо работает в других браузерах, в том числе в Chrome на OS X Lion, который также поддерживает пролистывание для возврата в историю. (В какой-то момент во время разработки прокрутка в div работала и в Safari. Я добавил обработчики событий и html, которые, вероятно, прервали прокрутку, но я понятия не имею, что заставило его измениться.)

В идеале, я бы хотел предотвратить переход назад или вперед в истории при прокрутке на конкретном div (даже когда он достиг конца).

Обновление: я попытался добавить jQuery.mousewheel , и это как-то решило проблему. (Я только что прикрепил пустой обработчик событий к .mousewheel().) Я все еще ищу окончательный ответ.

Ответы [ 6 ]

17 голосов
/ 19 ноября 2014

Чтобы разрешить элементу (например, <div>) прокручиваться с помощью трекпада, но запретить браузеру вернуться на предыдущую страницу, необходимо запретить действие браузера по умолчанию.

Вы можете сделать это, прослушивая событие mousewheel на элементе. Используя свойства прокрутки элемента и свойства 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);

Это работает на Chrome, Safari и Firefox на Mac. Я не тестировал на IE.

Это решение повлияет только на рассматриваемый элемент и позволит остальной части страницы вести себя как обычно. Таким образом, вы можете использовать свой браузер, как ожидалось, и вернуться на страницу, но, находясь внутри элемента, вы случайно не вернетесь назад, когда не хотели.

9 голосов
/ 24 января 2012

Я искал решение в течение нескольких дней.Пока что у меня есть этот плагин:

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

Он отключил прокрутку для OSX Chrome (я не смог найти способ отключить его для OSX Safari) при прокрутке влевои выше.

Надеюсь, это поможет, пожалуйста, внесите свой вклад в проект, если обнаружите какие-либо ошибки, или если вы найдете способ отключить это раздражающее поведение для Safari

9 голосов
/ 12 января 2012

Да, чтобы отключить поведение по умолчанию (смахивание, сжатие и т. Д.), Все что вам нужно сделать, это добавить:

event.preventDefault();

В вашем случае просто зарегистрируйте прослушиватель touchMove и используйте там функцию protectDefault () (в функции «touchmove»).

element.addEventListener("touchmove", touchMove, false);
2 голосов
/ 20 октября 2015

Посмотрите на стиль CSS3

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

Это прекрасно работает для меня, когда используемое приложение ожидается только в браузерах с поддержкой HTML5 / CSS3.

1 голос
/ 25 сентября 2013

Я также использовал колесо мыши 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
}
0 голосов
/ 17 мая 2017

Копилка от https://github.com/micho/jQuery.preventMacBackScroll от micho. Я сделал это возможным как в сафари, так и в 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()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...