evento di scorrimento javascript per iPhone / iPad?


107

Non riesco a catturare l'evento di scorrimento su un iPad. Nessuno di questi funziona, cosa sto facendo di sbagliato?

window.onscroll=myFunction;

document.onscroll=myFunction;

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

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

Funzionano tutti anche su Safari 3 su Windows. Ironia della sorte, OGNI browser sul PC supporta window.onload=se non ti dispiace distruggere gli eventi esistenti. Ma non andare su iPad.

Risposte:


146

L'iPhoneOS cattura gli onscrolleventi, tranne nel modo in cui ci si potrebbe aspettare.

La panoramica con un dito non genera alcun evento finché l'utente non interrompe la panoramica (un onscrollevento viene generato quando la pagina smette di spostarsi e viene ridisegnata), come mostrato nella Figura 6-1.

Allo stesso modo, lo scorrimento con 2 dita si attiva onscrollsolo dopo aver smesso di scorrere.

Il modo usuale di installare il gestore funziona ad es

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

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


23
Grazie, questo mi ha costretto a esaminare ulteriormente il problema. La vera risposta è stata rilevare la parte superiore del viewport su iphone / ipad funziona solo con window.pageYOffset e non document.body.scrollTop||document.documentElement.scrollTop come ogni altro browser / hardware esistente.
ck_

6
@ck_ Sfortunatamente su IPAD window.pageYOffsetnon si aggiorna nella fase di decelerazione, ma solo al termine dello scroll.
Adaptabi

2
È una cattiva pratica sovrascrivere direttamente window.onscroll. Aggiungere un listener di eventi sarebbe meglio. Usa window.addEventListener ('scroll', function () {alert ('scrolled!');});
Kevin Dice

4
ehm .. in realtà, window.onscroll sta sparando sul mio ipad tutto il tempo ora, durante il panning, e dopo il panning, mentre decelera. qualcosa è cambiato?
commonpike

Safari (e forse altri) sono passati all'uso di WKWebView con iOS 8. Chrome e Cordova utilizzano ancora UIWebView, quindi presentano ancora il problema con gli eventi di scorrimento continuo che non vengono emessi. Tuttavia, esiste un plug-in WKWebView per Cordova.
jiku

105

Per iOS è necessario utilizzare l' evento touchmove e l' evento di scorrimento in questo modo:

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
Questo evento viene generato solo quando l'utente sta scorrendo attivamente, non viene generato durante la fase di decelerazione dello scorrimento momentum.
Jon Tirsen

Ho cambiato il codice per includere il codice di rilevamento della fine dello scorrimento per iOS
George Filippakos

Potresti anche voler aggiungere un listener per "touchend" che agirà in modo simile allo scorrimento sul desktop.
BingeBoy

1
Nota che questo non fornisce l'accesso alla fase di scorrimento durante la fase di scorrimento
Ben Sewards

3
sono passati tre anni. Non riesco a ottenere un aggiornamento in tempo reale della posizione di scorrimento durante la decelerazione. come dovrei scrivere la mia app simile a mappe ?????
FlavorScape

38

Ci scusiamo per l'aggiunta di un'altra risposta a un vecchio post ma di solito ottengo molto bene un evento di scorrimento usando questo codice (funziona almeno su 6.1)

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

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

E per me funziona. L'unica cosa che non fa è fornire un evento di scorrimento per la decelerazione dello scorrimento (una volta completata la decelerazione si ottiene un evento di scorrimento finale, fare come si vuole) ma se si disabilita l'inerzia con css in questo modo

-webkit-overflow-scrolling: none;

Non ottieni inerzia sui tuoi elementi, per il corpo anche se potresti dover fare il classico

document.addEventListener('touchmove', function(e) {e.preventDefault();}, true);

7
Perché downvote una risposta valida e non lasciare un commento che spiega il problema con essa?
Dave Mackintosh

3
perché il downvoting è facile e veloce. : /
Zeshan Ahmed

5
Una risposta è SEMPRE "valida" secondo il suo autore ... Nessuno pubblica una risposta consapevolmente non valida. Ma sì, avrebbero dovuto spiegare perché hanno svalutato.
Matthieu Charbonnier,

3
gesturechangegli eventi non sono standard e sono supportati solo da Safari: developer.mozilla.org/en-US/docs/Web/Events/gesturechange
Nicolas Bouvrette

6

Sono stato in grado di ottenere un'ottima soluzione a questo problema con iScroll, con la sensazione dello scorrimento dello slancio e tutto il resto https://github.com/cubiq/iscroll Il documento github è fantastico e l'ho seguito principalmente. Ecco i dettagli della mia implementazione.

HTML: ho inserito l'area scorrevole dei miei contenuti in alcuni div che iScroll può utilizzare:

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

CSS: Ho usato la classe Modernizr per "touch" per indirizzare le mie modifiche di stile solo ai dispositivi touch (perché ho istanziato iScroll solo al tocco).

.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: ho incluso iscroll-probe.js dal download iScroll, quindi ho inizializzato lo scroller come sotto, dove updatePosition è la mia funzione che reagisce alla nuova posizione di scroll.

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

Devi usare myScroller per ottenere la posizione corrente ora, invece di guardare l'offset di scorrimento. Ecco una funzione tratta da http://markdalgleish.com/presentations/embracingtouch/ (un articolo super utile, ma un po 'datato ora)

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

L'unico altro trucco era che a volte perdevo parte della mia pagina che stavo cercando di scorrere e si rifiutava di scorrere. Ho dovuto aggiungere alcune chiamate a myScroller.refresh () ogni volta che cambiavo il contenuto del #wrapper, e questo risolveva il problema.

EDIT: Un altro problema era che iScroll mangia tutti gli eventi "clic". Ho attivato l'opzione per fare in modo che iScroll emetta un evento "tocco" e ho gestito quelli invece degli eventi "clic". Per fortuna non ho avuto bisogno di fare molto clic nell'area di scorrimento, quindi non è stato un grosso problema.


1

Da quando è uscito iOS 8, questo problema non esiste più. L'evento di scorrimento ora viene attivato senza problemi anche in iOS Safari.

Quindi, se registri il scrollgestore di eventi e controlli window.pageYOffsetall'interno di quel gestore di eventi, tutto funziona perfettamente.


1
Esiste ancora in alcuni casi d'uso come l'utilizzo di Cordova. developer.telerik.com/featured/…
diosney

6
La mia esperienza è che questo rimane ancora un problema con gli attuali dispositivi iOS nel 2019.
Chris
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.