Событие прокрутки javascript для iPhone / iPad?

107

Кажется, я не могу зафиксировать событие прокрутки на iPad. Ничего из этого не работает, что я делаю не так?

window.onscroll=myFunction;

document.onscroll=myFunction;

window.attachEvent("scroll",myFunction,false);

document.attachEvent("scroll",myFunction,false);

Все они работают даже в Safari 3 в Windows. По иронии судьбы, КАЖДЫЙ браузер на ПК поддерживает, window.onload=если вы не возражаете против уничтожения существующих событий. Но на iPad нет.

ck_
источник

Ответы:

147

IPhoneOS захватывает onscrollсобытия, но не так, как вы могли ожидать.

Панорамирование одним пальцем не генерирует никаких событий, пока пользователь не прекратит панорамирование - onscrollсобытие генерируется, когда страница перестает двигаться и перерисовывается - как показано на рисунке 6-1.

Точно так же прокрутка двумя пальцами срабатывает onscrollтолько после того, как вы прекратили прокрутку.

Обычный способ установки обработчика работает, например

window.addEventListener('scroll', function() { alert("Scrolled"); });
// or
$(window).scroll(function() { alert("Scrolled"); });
// or
window.onscroll = function() { alert("Scrolled"); };
// etc 

(См. Также https://developer.apple.com/library/content/documentation/AppleApplications/Reference/SafariWebContent/HandlingEvents/HandlingEvents.html )

Kennytm
источник
23
Спасибо, это заставило меня глубже взглянуть на проблему. Реальный ответ обнаруживал в верхней части окна просмотра на Iphone / Ipad работает только с window.pageYOffset и не document.body.scrollTop||document.documentElement.scrollTop как и любой другой браузер / аппаратных средств в существовании.
ck_
6
@ck_ К сожалению, на IPAD window.pageYOffsetне обновляется в фазе замедления, а только после завершения прокрутки.
Adaptabi
2
Прямая перезапись window.onscroll - плохая практика. Было бы лучше добавить слушателя событий. Используйте window.addEventListener ('scroll', function () {alert ('прокручивается!');});
Кевин Дайс
4
эээ ... на самом деле window.onscroll срабатывает на моем ipad все время теперь, при панорамировании, и после панорамирования, при замедлении. что-то изменилось?
commonpike
Safari (и, возможно, другие) перешли на использование WKWebView с iOS 8. Chrome и Cordova по-прежнему используют UIWebView, поэтому у них по-прежнему возникает проблема с не выдачей событий непрерывной прокрутки. Хотя для Кордовы есть подключаемый модуль WKWebView.
jiku
105

Для iOS вам нужно использовать событие touchmove, а также событие прокрутки, например:

document.addEventListener("touchmove", ScrollStart, false);
document.addEventListener("scroll", Scroll, false);

function ScrollStart() {
    //start of scroll event for iOS
}

function Scroll() {
    //end of scroll event for iOS
    //and
    //start/end of scroll event for other browsers
}
Джордж Филиппакос
источник
37
Это событие запускается только тогда, когда пользователь активно прокручивает, оно не запускается во время фазы замедления прокрутки импульса.
Джон Тирсен,
я изменил код, чтобы включить код обнаружения конца прокрутки для iOS
Джордж Филиппакос,
Вы также можете добавить слушателя для «touchend», который будет действовать аналогично прокрутке на рабочем столе.
BingeBoy
1
Обратите внимание, что это не обеспечивает доступ к фазе прокрутки
Бен Сьюардс,
3
прошло три года. Я не могу получить обновление положения прокрутки в реальном времени во время замедления. как мне написать приложение, похожее на карты ?????
FlavorScape
38

Извините за добавление другого ответа к старому сообщению, но я обычно очень хорошо получаю событие прокрутки, используя этот код (он работает, по крайней мере, на 6.1)

element.addEventListener('scroll', function() {
    console.log(this.scrollTop);
});

// This is the magic, this gives me "live" scroll events
element.addEventListener('gesturechange', function() {});

И это работает для меня. Единственное, чего он не делает, это дает событие прокрутки для замедления прокрутки (после завершения замедления вы получаете последнее событие прокрутки, сделайте с ним то же, что и вы.), Но если вы отключите инерцию с помощью css, сделав это

-webkit-overflow-scrolling: none;

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

document.addEventListener('touchmove', function(e) {e.preventDefault();}, true);
Дэйв Макинтош
источник
7
Зачем голосовать против правильного ответа и не оставлять комментарий, объясняющий проблему с ним?
Dave Mackintosh
3
потому что голосование против - это просто и быстро. : /
Зешан Ахмед
5
Ответ ВСЕГДА "действителен" по словам его автора ... Никто не отправляет заведомо неверный ответ. Но да, им следовало объяснить, почему они проголосовали против.
Matthieu Charbonnier
3
gesturechangeсобытия нестандартны и поддерживаются только Safari: developer.mozilla.org/en-US/docs/Web/Events/gesturechange
Николя Буврет
6

Я смог получить отличное решение этой проблемы с помощью iScroll, с ощущением динамической прокрутки и всем остальным https://github.com/cubiq/iscroll Документ github великолепен, и я в основном следил за ним. Вот подробности моей реализации.

HTML: я обернул прокручиваемую область моего контента в некоторые div, которые может использовать iScroll:

<div id="wrapper">
  <div id="scroller">
    ... my scrollable content
  </div>
</div>

CSS: я использовал класс Modernizr для «прикосновения», чтобы нацелить изменения моего стиля только на сенсорные устройства (потому что я создавал экземпляр iScroll только при касании).

.touch #wrapper {
  position: absolute;
  z-index: 1;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  overflow: hidden;
}
.touch #scroller {
  position: absolute;
  z-index: 1;
  width: 100%;
}

JS: Я включил iscroll-probe.js из загрузки iScroll, а затем инициализировал скроллер, как показано ниже, где updatePosition - моя функция, которая реагирует на новую позицию прокрутки.

# coffeescript
if Modernizr.touch
  myScroller = new IScroll('#wrapper', probeType: 3)
  myScroller.on 'scroll', updatePosition
  myScroller.on 'scrollEnd', updatePosition

Теперь вам нужно использовать myScroller, чтобы получить текущую позицию, вместо того, чтобы смотреть на смещение прокрутки. Вот функция, взятая из http://markdalgleish.com/presentations/embracingtouch/ (очень полезная статья, но сейчас она немного устарела)

function getScroll(elem, iscroll) {   
  var x, y;

  if (Modernizr.touch && iscroll) {
    x = iscroll.x * -1;
    y = iscroll.y * -1;   
  } else {
    x = elem.scrollTop;
    y = elem.scrollLeft;   
  }

  return {x: x, y: y}; 
}

Единственная другая проблема заключалась в том, что иногда я терял часть своей страницы, на которую я пытался прокрутить, и она отказывалось прокручиваться. Мне приходилось добавлять несколько вызовов myScroller.refresh () всякий раз, когда я менял содержимое #wrapper, и это решало проблему.

РЕДАКТИРОВАТЬ: Еще одна проблема заключалась в том, что iScroll съедает все события щелчка. Я включил опцию, чтобы iScroll генерировал событие «касание» и обрабатывал его вместо событий «щелчок». К счастью, мне не нужно было много щелкать в области прокрутки, так что это не имело большого значения.

Мелинда Уэзерс
источник
1

С выходом iOS 8 этой проблемы больше не существует. Событие прокрутки теперь плавно запускается и в iOS Safari.

Итак, если вы зарегистрируете scrollобработчик событий и загляните window.pageYOffsetвнутрь этого обработчика событий, все будет работать нормально.

Маттиас Болен
источник
1
Он существует еще в некоторых случаях использования, таких как использование Cordova. developer.telerik.com/featured/…
diosney
7
Мой опыт показывает, что эта проблема все еще остается проблемой для текущих устройств iOS в 2019 году.
Крис