Как мне предотвратить поведение события touchmove по умолчанию в iOS 5?

#javascript #ios5 #dom-events #preventdefault

#javascript #ios5 #dom-события #preventdefault

Вопрос:

У меня есть веб-приложение, которое включает в себя компонент, который пользователь может прокручивать вверх и вниз пальцем. Я использую метод события preventDefault , чтобы предотвратить поведение по умолчанию, когда перемещение касания перемещает весь экран на устройствах iOS.

К сожалению, похоже, что это больше не работает в iOS 5, которую я только что обновил сегодня утром. Я должен предположить, что это просто делается по-другому в iOS 5, но мне еще предстоит найти ресурс, который предоставляет инструкции.

Обновление # 1: я не смог найти ответ на свой конкретный вопрос, но я смог немного скорректировать свой код, чтобы использовать -webkit-overflow-scrolling стиль (заданный значением «touch») и реализовать возможность быстрой инерционной прокрутки (где содержимое прокручивается быстрее в зависимости от скорости вашегопроведите пальцем и «резиновая лента отскочит» назад, если она достигнет границ. Довольно круто выглядит…

Обновление # 2: теперь у меня еще одна странная проблема. По какой-то странной причине поведение прокрутки при переполнении иногда путается, когда вам приходится перетаскивать палец влево и вправо по содержащему элементу, чтобы заставить его содержимое перемещаться вверх и вниз. Я еще не смог понять, почему это происходит — у кого-нибудь есть идеи?

Ответ №1:

Я нашел очень простое решение. Когда событие попадает на ваш элемент, которому разрешено прокручивать, просто отметьте событие. В прослушивателе событий в документе просто проверьте, установлен ли флаг, и остановите событие, только если флаг не установлен:

 this.$scrollableEl.on('touchmove', function(event){
  event.comesFromScrollable = true;
  // when you have containers that are srollable but 
  // doesn't have enough content to scroll sometimes:
  // event.comesFromScrollable = el.offsetHeight < el.scrollHeight;
});

$(document).on('touchmove', function(event){
    if (!event.comesFromScrollable){
      event.preventDefault();
    }
});
  

Вместо этого вы также можете использовать event.stopimmediateprop, поэтому вам не нужен EventListener для элемента document, но это нарушает zepto.js tap в моем случае:

 this.$scrollableEl.on('touchmove', function(event){
  event.stopImmediatePropagation();
});
  

Комментарии:

1. Спасибо! Работает как шарм! Я изменил его таким образом, что я просто добавляю пользовательский атрибут данных, и если он доступен, прокрутка не будет остановлена. таким образом, мы можем сохранить один eventlistener 🙂

Ответ №2:

Во-первых, я могу проверить, что e.preventDefault() отключает всю прокрутку в iOS 5, используя следующий код:

 document.ontouchmove = function(e){ e.preventDefault(); }
  

К сожалению, однако, это отключает прокрутку при переполнении: прокрутка divs. (Если у кого-нибудь есть решение, которое оставляет прокрутку внутреннего элемента включенной, пожалуйста, поделитесь.)

Что касается обновления № 2, я заметил странное поведение, когда прокручиваемый элемент вложен в другой прокручиваемый элемент (включая саму страницу). Иногда устройство не знает, какой элемент пользователь намеревается прокрутить. В частности, я заметил эту проблему, используя position:fixed. Мое решение состояло в том, чтобы убедиться, что тело имеет 100% высоту и что прокручиваемые элементы используют position:absolute, где это возможно.

Комментарии:

1. Может быть, вы могли бы выполнить некоторую проверку логики, например if($(e.currentTarget).css('overflow') != 'scroll') e.preventDefault(); . Поскольку document.ontouchmove запускается после ontouchmove элемента scollable, вы можете выполнить el.ontouchmove = function() {allowScroll = true} , а затем document.ontouchmove использовать это значение для определения действия, а затем вернуть значение false .

2. @BrianNickel Спасибо за совет. Это шаг в правильном направлении, который позволит вам запретить прямую прокрутку поэлементно (включая прямую прокрутку тела), но если пользователь коснется прокручиваемого элемента, который уже находится на границе его диапазона прокрутки, он все равно будет прокручивать тело(показано серое белье внизу). Возможно, единственный способ — интерпретировать направление touchmove и проверить, находится ли элемент на границе его диапазона прокрутки?

3. @RyanRapp Спасибо за ваш ответ. Возможно, я недостаточно четко описал, о каком поведении я говорю. В iOS 4 я бы использовал e.preventDefault() внутри элемента (скажем, DIV) с обработчиком события touchmove от overflow, чтобы я мог перемещать содержимое с помощью абсолютного позиционирования на основе движения пальца внутри элемента. Теперь e.preventDefault() блокирует это, когда я пытаюсь переместить палец на всю страницу, на которой недостаточно содержимого для прокрутки, не столько прокручивается, сколько перемещается, чтобы вы могли видеть фоновую текстуру Safari за ней.

4. Это решение очень помогло мне с моим веб-приложением. Приветствия!