Javascript Scroll Event für iPhone / iPad?

107

Ich kann das Scroll-Ereignis scheinbar nicht auf einem iPad erfassen. Keine dieser Arbeiten, was mache ich falsch?

window.onscroll=myFunction;

document.onscroll=myFunction;

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

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

Sie alle funktionieren sogar unter Safari 3 unter Windows. Ironischerweise unterstützt JEDER Browser auf dem PC, window.onload=wenn es Ihnen nichts ausmacht, vorhandene Ereignisse zu überfrachten. Aber nicht auf das iPad gehen.

ck_
quelle

Antworten:

146

Das iPhoneOS erfasst onscrollEreignisse, außer nicht so, wie Sie es erwarten.

Das Ein-Finger-Schwenken generiert keine Ereignisse, bis der Benutzer das Schwenken beendet - ein onscrollEreignis wird generiert, wenn sich die Seite nicht mehr bewegt und neu zeichnet - wie in Abbildung 6-1 dargestellt.

In ähnlicher Weise wird onscrolldas Scrollen mit 2 Fingern erst ausgelöst , nachdem Sie das Scrollen beendet haben.

Die übliche Art der Installation des Handlers funktioniert z

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

(Siehe auch https://developer.apple.com/library/content/documentation/AppleApplications/Reference/SafariWebContent/HandlingEvents/HandlingEvents.html )

kennytm
quelle
23
Danke, das hat mich gezwungen, das Problem weiter zu untersuchen. Die eigentliche Antwort bestand darin, zu erkennen, dass die Oberseite des Ansichtsfensters auf dem iPhone / iPad nur mit jedem anderen existierenden Browser / Hardware funktioniert window.pageYOffset und nicht document.body.scrollTop||document.documentElement.scrollTopwie dieser funktioniert .
ck_
6
@ck_ Leider wird IPAD window.pageYOffsetin der Verzögerungsphase nicht aktualisiert, sondern nur, wenn der Bildlauf abgeschlossen ist.
Adaptabi
2
Es ist eine schlechte Praxis, window.onscroll direkt zu überschreiben. Das Hinzufügen eines Ereignis-Listeners wäre besser. Verwenden Sie window.addEventListener ('scroll', function () {alert ('scrolled!');});
Kevin Dice
4
ehm .. eigentlich feuert window.onscroll jetzt die ganze Zeit auf meinem iPad, während ich schwenke und nach dem Schwenken, während ich bremse. hat sich etwas geändert?
Commonpike
Safari (und möglicherweise andere) haben WKWebView mit iOS 8 verwendet. Chrome und Cordova verwenden weiterhin UIWebView, sodass das Problem weiterhin besteht, dass keine fortlaufenden Bildlaufereignisse ausgegeben werden. Es gibt jedoch ein WKWebView-Plug-In für Cordova.
Jiku
105

Für iOS müssen Sie das Touchmove- Ereignis sowie das Scroll- Ereignis wie folgt verwenden :

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
}
George Filippakos
quelle
37
Dieses Ereignis wird nur ausgelöst, wenn der Benutzer aktiv scrollt. Es wird nicht während der Verzögerungsphase des Impulslaufs ausgelöst.
Jon Tirsen
Ich habe den Code geändert, um den End-Scroll-Erkennungscode für iOS
George Filippakos
Möglicherweise möchten Sie auch einen Listener für "touchend" hinzufügen, der sich ähnlich wie das Scrollen auf dem Desktop verhält.
BingeBoy
1
Beachten Sie, dass dies keinen Zugriff auf die während der Bildlaufphase
Ben Sewards
3
Es ist drei Jahre her. Ich kann während der Verzögerung keine Echtzeitaktualisierung der Bildlaufposition erhalten. Wie soll ich meine kartenähnliche App schreiben ?????
FlavorScape
38

Es tut mir leid, dass ich einem alten Beitrag eine weitere Antwort hinzugefügt habe, aber normalerweise erhalte ich mit diesem Code sehr gut ein Bildlaufereignis (es funktioniert mindestens unter 6.1).

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

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

Und das funktioniert bei mir. Das einzige, was es nicht tut, ist ein Bildlaufereignis für die Verzögerung des Bildlaufs anzugeben (Sobald die Verzögerung abgeschlossen ist, erhalten Sie ein endgültiges Bildlaufereignis, machen Sie es wie Sie wollen.), Aber wenn Sie die Trägheit mit CSS auf diese Weise deaktivieren

-webkit-overflow-scrolling: none;

Sie bekommen keine Trägheit auf Ihre Elemente, für den Körper, obwohl Sie möglicherweise den Klassiker machen müssen

document.addEventListener('touchmove', function(e) {e.preventDefault();}, true);
Dave Mackintosh
quelle
7
Warum eine gültige Antwort ablehnen und keinen Kommentar hinterlassen, der das Problem erklärt?
Dave Mackintosh
3
weil das Downvoting einfach und schnell ist. : /
Zeshan Ahmed
5
Eine Antwort ist laut Autor IMMER "gültig" ... Niemand veröffentlicht eine wissentlich ungültige Antwort. Aber ja, sie hätten erklären sollen, warum sie abgelehnt haben.
Matthieu Charbonnier
3
gesturechangeEreignisse sind nicht Standard und werden nur von Safari unterstützt: developer.mozilla.org/en-US/docs/Web/Events/gesturechange
Nicolas Bouvrette
6

Ich konnte mit iScroll eine großartige Lösung für dieses Problem finden, mit dem Gefühl des Momentum-Scrollings und allem https://github.com/cubiq/iscroll Das Github-Dokument ist großartig und ich habe es größtenteils befolgt. Hier sind die Details meiner Implementierung.

HTML: Ich habe den scrollbaren Bereich meines Inhalts in einige Divs eingeschlossen, die iScroll verwenden kann:

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

CSS: Ich habe die Modernizr-Klasse für "touch" verwendet, um meine Stiländerungen nur auf Touch-Geräte auszurichten (da ich iScroll nur bei Berührung instanziiert habe).

.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: Ich habe iscroll-probe.js aus dem iScroll-Download aufgenommen und dann den Scroller wie folgt initialisiert, wobei updatePosition meine Funktion ist, die auf die neue Scrollposition reagiert.

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

Sie müssen myScroller verwenden, um die aktuelle Position zu ermitteln, anstatt den Bildlaufversatz zu betrachten. Hier ist eine Funktion von http://markdalgleish.com/presentations/embracingtouch/ (ein super hilfreicher Artikel, aber jetzt etwas veraltet).

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}; 
}

Das einzige andere Problem war, dass ich gelegentlich einen Teil meiner Seite verlor, zu der ich scrollen wollte, und sich weigerte, zu scrollen. Ich musste myScroller.refresh () immer dann aufrufen, wenn ich den Inhalt des #wrapper änderte, und das löste das Problem.

EDIT: Ein weiteres Problem war, dass iScroll alle "Klick" -Ereignisse isst. Ich habe die Option aktiviert, dass iScroll ein "Tap" -Ereignis ausgibt, und diese anstelle von "Click" -Ereignissen behandelt. Zum Glück musste ich nicht viel in den Bildlaufbereich klicken, also war das keine große Sache.

Melinda Weathers
quelle
1

Seit dem Erscheinen von iOS 8 besteht dieses Problem nicht mehr. Das Scroll-Ereignis wird jetzt auch in iOS Safari reibungslos ausgelöst.

Wenn Sie also den scrollEreignishandler registrieren und window.pageYOffsetin diesen Ereignishandler einchecken , funktioniert alles einwandfrei.

Matthias Bohlen
quelle
1
Es existiert noch in einigen Anwendungsfällen wie der Verwendung von Cordova. developer.telerik.com/featured/…
Diosney
6
Ich habe die Erfahrung gemacht, dass dies 2019 immer noch ein Problem mit aktuellen iOS-Geräten ist.
Chris