evento de desplazamiento de JavaScript para iPhone / iPad?

107

Parece que no puedo capturar el evento de desplazamiento en un iPad. Ninguno de estos funciona, ¿qué estoy haciendo mal?

window.onscroll=myFunction;

document.onscroll=myFunction;

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

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

Todos funcionan incluso en Safari 3 en Windows. Irónicamente, TODOS los navegadores de la PC son compatibles window.onload=si no le importa eliminar los eventos existentes. Pero no vayas al iPad.

ck_
fuente

Respuestas:

146

El iPhoneOS captura onscrolleventos, excepto que no de la forma esperada .

La panorámica con un dedo no genera ningún evento hasta que el usuario deja de desplazarse ( onscrollse genera un evento cuando la página deja de moverse y se vuelve a dibujar), como se muestra en la Figura 6-1.

Del mismo modo, desplácese con 2 dedos onscrollsolo después de que haya dejado de desplazarse.

La forma habitual de instalar el controlador funciona, por ejemplo,

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

(Consulte también https://developer.apple.com/library/content/documentation/AppleApplications/Reference/SafariWebContent/HandlingEvents/HandlingEvents.html )

Kennytm
fuente
23
Gracias, eso me obligó a seguir analizando el problema. La respuesta real fue detectar la parte superior de la ventana gráfica en el iphone / ipad que solo funciona con window.pageYOffset y no document.body.scrollTop||document.documentElement.scrollTop como cualquier otro navegador / hardware existente.
ck_
6
@ck_ Desafortunadamente en iPad window.pageYOffsetno se actualiza en la fase de desaceleración, sino solo cuando termina el desplazamiento.
Adaptabi
2
Es una mala práctica sobrescribir directamente window.onscroll. Sería mejor agregar un detector de eventos. Use window.addEventListener ('scroll', function () {alert ('scrolled!');});
Kevin Dice
4
ehm ... en realidad, window.onscroll se dispara en mi ipad todo el tiempo ahora, mientras se realiza una panorámica, y después de una panorámica, mientras se desacelera. algo cambió?
commonpike
Safari (y tal vez otros) cambió para usar WKWebView con iOS 8. Chrome y Cordova todavía usan UIWebView, por lo que aún presentan el problema con eventos de desplazamiento continuo que no se emiten. Sin embargo, hay un complemento WKWebView para Cordova.
jiku
105

Para iOS, debe usar el evento touchmove , así como el evento de desplazamiento como este:

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
fuente
37
Este evento solo se activa cuando el usuario se desplaza activamente, no se activa durante la fase de desaceleración del desplazamiento de impulso.
Jon Tirsen
cambié el código para incluir el código de detección de desplazamiento final para iOS
George Filippakos
Es posible que también desee agregar un oyente para "tocar" que actuará de manera similar al desplazamiento en el escritorio.
BingeBoy
1
Tenga en cuenta que esto no proporciona acceso durante la fase de desplazamiento
Ben Sewards
3
han pasado tres años. No puedo obtener una actualización en tiempo real de la posición de desplazamiento durante la desaceleración. ¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿?????
FlavorScape
38

Perdón por agregar otra respuesta a una publicación anterior, pero generalmente obtengo un evento de desplazamiento muy bien al usar este código (funciona al menos en 6.1)

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

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

Y eso funciona para mí. Lo único que no hace es dar un evento de desplazamiento para la desaceleración del desplazamiento (una vez que se completa la desaceleración, obtiene un evento de desplazamiento final, haga lo que quiera con él), pero si deshabilita la inercia con css haciendo esto

-webkit-overflow-scrolling: none;

No tienes inercia en tus elementos, para el cuerpo, aunque es posible que tengas que hacer el clásico

document.addEventListener('touchmove', function(e) {e.preventDefault();}, true);
Dave Mackintosh
fuente
7
¿Por qué rechazar una respuesta válida y no dejar un comentario que explique el problema?
Dave Mackintosh
3
porque votar negativamente es fácil y rápido. : /
Zeshan Ahmed
5
Una respuesta SIEMPRE es "válida" según su autor ... Nadie publica una respuesta conscientemente inválida. Pero sí, deberían haber explicado por qué votaron en contra.
Matthieu Charbonnier
3
gesturechangeevents no es estándar y solo es compatible con Safari: developer.mozilla.org/en-US/docs/Web/Events/gesturechange
Nicolas Bouvrette
6

Pude obtener una gran solución a este problema con iScroll, con la sensación de desplazamiento por impulso y todo https://github.com/cubiq/iscroll El documento de github es genial, y lo seguí principalmente. Aquí están los detalles de mi implementación.

HTML: Envolví el área desplazable de mi contenido en algunos divs que iScroll puede usar:

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

CSS: utilicé la clase Modernizr para "toque" para orientar mis cambios de estilo solo a dispositivos táctiles (porque solo he instanciado iScroll al tocar).

.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: Incluí iscroll-probe.js de la descarga de iScroll y luego inicialicé el scroller como se muestra a continuación, donde updatePosition es mi función que reacciona a la nueva posición de scroll.

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

Debe usar myScroller para obtener la posición actual ahora, en lugar de mirar el desplazamiento de desplazamiento. Aquí hay una función tomada de http://markdalgleish.com/presentations/embracingtouch/ (un artículo muy útil, pero un poco desactualizado ahora)

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

El único otro problema era que ocasionalmente perdía parte de mi página a la que estaba tratando de desplazarme, y se negaba a desplazarse. Tuve que agregar algunas llamadas a myScroller.refresh () cada vez que cambiaba el contenido del #wrapper, y eso resolvió el problema.

EDITAR: Otro problema fue que iScroll se come todos los eventos de "clic". Activé la opción para que iScroll emitiera un evento de "toque" y los manejé en lugar de eventos de "clic". Afortunadamente no necesité hacer mucho clic en el área de desplazamiento, así que esto no fue un gran problema.

Melinda Weathers
fuente
1

Desde que salió iOS 8, este problema ya no existe. El evento de desplazamiento ahora también se activa sin problemas en iOS Safari.

Entonces, si registra el scrollcontrolador de eventos y verifica window.pageYOffsetdentro de ese controlador de eventos, todo funcionará bien.

Matthias Bohlen
fuente
1
Todavía existe en algunos casos de uso, como el uso de Cordova. developer.telerik.com/featured/…
diosney
6
Mi experiencia es que esto sigue siendo un problema con los dispositivos iOS actuales en 2019.
Chris