Невозможно предотвратить "touchmove" из окна прокрутки на iOS
Мы пытаемся прокрутить элемент в нашем веб-приложении iOS, не допуская прокрутки самого окна. Мы захватываем событие touchmove
в окне, прокручивая элемент программно и (пытаясь) предотвратить само окно прокрутки, вызвав preventDefault
на событие.
К сожалению, это не работает в Mobile Safari. Окно продолжает прокручиваться под нашим элементом. Проблема звучит точно так же, как ошибка Webkit, описанная в https://bugs.webkit.org/show_bug.cgi?id=163207, но эта проблема предположительно была исправлена в iOS 10.3, тогда как я запускаю 11.3.
touchforcestart
и вызов preventDefault
, похоже, не позволяют прокручивать окно, но мы вызываем его в touchstart
, который кажется "слишком поздним", поскольку окно все еще прокручивается. Прокрутка только предотвращается в следующий раз, touchstart
вызывается touchstart
.
Любые идеи о том, что происходит? Мы сбиты с толку, потому что это явно ошибка, но, похоже, она была исправлена некоторое время назад.
Ответы
Ответ 1
Недавно я столкнулся с этой проблемой. Вам необходимо передать { passive: false }
при регистрации touchmove
событий touchmove
. например
document.addEventListener('touchmove', function(e) {
e.preventDefault();
}, { passive: false });
Это связано с тем, что прослушиватели событий с сенсорными сообщениями теперь по умолчанию пассивны в Safari 11.1, который поставляется вместе с iOS 11.3. Это изменение задокументировано в примечаниях к выпуску Safari 11.1:
Веб-интерфейсы
- [...]
- Обновленные корневые файлы для прослушивания сообщений о событии для использования пассивного режима улучшают производительность прокрутки и уменьшают количество сбоев.
Ответ 2
Вам нужно привязать preventDefault
к двум событиям: touchmove
и touchforcechange
, чтобы заставить его работать в ios 11, например
document.addEventListener('touchmove', this.preventDefault, {passive: false});
document.addEventListener('touchforcechange', this.preventDefault, {passive: false});
И вы должны связать их перед началом сенсорного запуска
Если вы связываете их внутри обработчика touchstart
или dragStart
, они могут только предотвратить прокрутку при следующем перетаскивании.