ipad safari: ¿deshabilitar el desplazamiento y el efecto de rebote?

126

Estoy trabajando en una aplicación basada en navegador, actualmente estoy desarrollando y diseñando para el navegador ipad safari.

Estoy buscando dos cosas en el ipad: ¿Cómo puedo desactivar el desplazamiento vertical para páginas que no lo requieren? ¿Y cómo puedo desactivar el efecto de rebote elástico?

Adán
fuente
consulte la siguiente respuesta solo una que funcionó para mí y es actual ( stackoverflow.com/a/51176339/1979180 )
frage

Respuestas:

157

Esta respuesta ya no es aplicable, a menos que esté desarrollando para un dispositivo iOS muy antiguo ... Consulte otras soluciones


Respuesta de 2011: para una aplicación web / html que se ejecute dentro de iOS Safari, desea algo como

document.ontouchmove = function(event){
    event.preventDefault();
}

Para iOS 5, puede tener en cuenta lo siguiente: document.ontouchmove y desplazamiento en iOS 5

Actualización de septiembre de 2014: se puede encontrar un enfoque más completo aquí: https://github.com/luster-io/prevent-overscroll . Para eso y muchos consejos útiles sobre aplicaciones web, consulte http://www.luster.io/blog/9-29-14-mobile-web-checklist.html

Actualización de marzo de 2016: ese último enlace ya no está activo: consulte https://web.archive.org/web/20151103001838/http://www.luster.io/blog/9-29-14-mobile-web-checklist .html para la versión archivada en su lugar. Gracias @falsarella por señalar eso.

Oskar Austegard
fuente
1
Tengo una aplicación web ejecutándose dentro de iOS Safari y he intentado deshabilitar el evento ontouchmove, pero aún es posible ver el efecto de rebote si se hace con cuidado. (iOS 5)
Nilesh
77
¿Qué pasa con solo deshabilitar el efecto de rebote ...?
Yuval A.
66
El problema con este enfoque es que los divs desplazables en su dom ya no se desplazarán. Dependiendo de su configuración de dom, hay formas de evitar esto.
huesforalice
3
Hay un montón de personas que preguntan sobre los divs de desplazamiento mientras usan esto, así que ... para hacer que esos divs se puedan desplazar, agregue onTouchMove: function(e) { e.stopPropagation(); e.stopImmediatePropagation(); } Evitará que el evento golpee el cuerpo, pero el cuerpo permanecerá sin rebote. Editar: Esto supone que establezca $ ('div'). On ('touchmove', ... onTouchMove);
Matt Kenefick
1
@OskarAustegard El último enlace no funcionó para mí, pero pude encontrar el contenido en el archivo web: web.archive.org/web/20151103001838/http://www.luster.io/blog/…
falsarella
116

También puede cambiar la posición del cuerpo / html a fija:

body,
html {
  position: fixed;
}
Ben Bos
fuente
2
Esto realmente funcionó muy bien en iPad iOS 8.2 Safari; sin efecto de rebote más.
Akseli Palén
3
La mejor manera de hacerlo que he visto hasta ahora
hildende
8
No funciona si desea colocar algo con posición: absoluto y todos los lados establecidos en 0 (para hacer un div de pantalla completa): todo su documento se reduce a nada.
riv
44
La página vuelve a la parte superior de la página cuando la uso y luego me concentro en una entrada. ¿Conoces una forma de evitar esto?
Julie
1
Ancho de adición de @riv: 100%; altura: 100% para el cuerpo y html me ayudó.
Tim
57

Para evitar el desplazamiento en los navegadores móviles modernos, debe agregar el pasivo: falso. Había estado arrancándome el pelo para que esto funcionara hasta que encontré esta solución. Solo he encontrado esto mencionado en otro lugar en Internet.

function preventDefault(e){
    e.preventDefault();
}

function disableScroll(){
    document.body.addEventListener('touchmove', preventDefault, { passive: false });
}
function enableScroll(){
    document.body.removeEventListener('touchmove', preventDefault);
}

Christopher Vickers
fuente
77
Sin { passive: false }definitivamente no funciona! Bienvenido en StackOverflow dude
Ser
2
¡Te agradezco por proporcionar esta solución!
Paul Z.
66
Esta es la respuesta correcta. Puede ver la explicación aquí: developer.mozilla.org/en-US/docs/Web/API/EventTarget/… después de que Chrome 54 touchmove pasara por defecto a verdadero, lo que significa que se ignorarían las llamadas preventDefault. Es por eso que debe pasar {pasivo: falso}, para que no se ignore la llamada preventDefault.
derickito
1
Estás declarando la función en JS, pero ¿cómo llamas a esta función en un elemento para que funcione como se sugiere?
ikwyl6
44
Esto funciona muy bien si desea deshabilitar todo tipo de desplazamiento. Pero, ¿qué sucede si solo quiero desactivar el desplazamiento en el cuerpo y mantener la posibilidad de desplazarme en un elemento overflow-y: scroll? Por ejemplo, tener un modal con una altura de vista más alta que el cuerpo.
Calsal
7

Puede usar este fragmento de código jQuery para hacer esto:

$(document).bind(
      'touchmove',
          function(e) {
            e.preventDefault();
          }
);

Esto bloqueará el desplazamiento vertical y también cualquier efecto de rebote que ocurra en sus páginas.

Alessandro Incarnati
fuente
11
Esto no es Javascript, es jQuery. Debe mencionar que, no todos están usando ese marco.
inta
¿Cómo puedo detener el rebote horizontal o el desplazamiento?
Fidel Castro
Desplazamiento horizontal, incluso podría deshabilitarlo con solo css, aplicando overflow-x: hidden; a su contenedor principal. Sin embargo, noté que en las últimas versiones de safari no puede deshabilitar el efecto de rebote. Es una característica nativa del navegador en dispositivos móviles.
Alessandro Incarnati
66
@inta Solo digo que esto en realidad es javascript. Simplemente no es javascript puro.
Ben Lorantfy
6
overflow: scroll;
-webkit-overflow-scrolling: touch;

En el contenedor puede establecer el efecto de rebote dentro del elemento

Fuente: http://www.kylejlarson.com/blog/2011/fixed-elements-and-scrolling-divs-in-ios-5/

usuario956584
fuente
1
Junto con overflow:hiddenel <body>, esta sigue siendo la mejor solución. Sin embargo, al abrir el teclado o deslizarse por la parte inferior de la pantalla, ya no funcionará.
Fabian von Ellerts
intente ingresar onfocus eliminar desbordamiento
user956584
4

Sé que esto está un poco fuera de pista, pero he estado usando Swiffy para convertir Flash en un juego HTML5 interactivo y me encontré con el mismo problema de desplazamiento, pero no encontré soluciones que funcionaran.

El problema que tuve fue que la etapa Swiffy ocupaba toda la pantalla, por lo que tan pronto como se cargó, el evento de movimiento táctil del documento nunca se activó.

Si intenté agregar el mismo evento al contenedor Swiffy, se reemplazó tan pronto como se cargó el escenario.

Al final lo resolví (bastante desordenado) aplicando el evento touchmove a cada DIV dentro del escenario. Como estos divs también cambiaban constantemente, necesitaba seguir revisándolos.

Esta fue mi solución, que parece funcionar bien. Espero que sea útil para cualquier otra persona que intente encontrar la misma solución que yo.

var divInterval = setInterval(updateDivs,50);
function updateDivs(){
$("#swiffycontainer > div").bind(
    'touchmove',
     function(e) {
        e.preventDefault();
    }
);}
Tom
fuente
esto deshabilita todo el desplazamiento en el ipad
fidel castro
3

Código para eliminar ipad safari: deshabilite el desplazamiento y el efecto de rebote

   document.addEventListener("touchmove", function (e) {
        e.preventDefault();
    }, { passive: false });

Si tiene una etiqueta de lienzo dentro del documento, en algún momento afectará la usabilidad del objeto dentro del lienzo (ejemplo: movimiento del objeto); así que agregue el siguiente código para solucionarlo.

    document.getElementById("canvasId").addEventListener("touchmove", function (e) {
        e.stopPropagation();
    }, { passive: false });
Teju VB
fuente
2

Prueba esta solución JS :

var xStart, yStart = 0; 

document.addEventListener('touchstart', function(e) {
    xStart = e.touches[0].screenX;
    yStart = e.touches[0].screenY;
}); 

document.addEventListener('touchmove', function(e) {
    var xMovement = Math.abs(e.touches[0].screenX - xStart);
    var yMovement = Math.abs(e.touches[0].screenY - yStart);
    if((yMovement * 3) > xMovement) {
        e.preventDefault();
    }
});

Evita el desplazamiento predeterminado de Safari y los gestos de rebote sin desconectar a los oyentes de eventos táctiles.

Andrii Verbytskyi
fuente
Esto evita que la aplicación web se desplace por completo en el elemento del cuerpo.
MartijnICU
2

Ninguna de las soluciones funciona para mí. Así es como lo hago.

  html,body {
      position: fixed;
      overflow: hidden;
    }
  .the_element_that_you_want_to_have_scrolling{
      -webkit-overflow-scrolling: touch;
  }
kiwi enojado
fuente
Haría .the_element_that_you_want_to_have_scrolling {scrolling: touch; }
Roy Segall
Su respuesta funcionó para mí para el html, body pero no puedo hacer que "the_element_that_you_want_to_have_scrolling" se desplace. Este elemento está anidado dentro de unos pocos divs que están debajo del cuerpo. ¿Importa cuáles serían las etiquetas de elementos típicas para este div anidado que quiero que se desplace? Tengo puesto: relativo.
ikwyl6
1

Para aquellos que usan MyScript, la aplicación web y están luchando con el desplazamiento / arrastre del cuerpo (en iPad y tabletas) en lugar de escribir:

<body touch-action="none" unresolved>

Eso me lo arregló.

Miró
fuente
1

Puede usar js para evitar el desplazamiento:

let body = document.body;

let hideScroll = function(e) {
  e.preventDefault();
};

function toggleScroll (bool) {

  if (bool === true) {
    body.addEventListener("touchmove", hideScroll);
  } else {
    body.removeEventListener("touchmove", hideScroll);
  }
}

Y que simplemente ejecutar / detener funciones toggleScrollcuando abres / cierras modal.

Me gusta esto toggleScroll(true) / toggleScroll(false)

(Esto es solo para iOS, en Android no funciona)

Vlad Novikov
fuente
1

Pruebe esta solución JS que alterna el webkitOverflowScrollingestilo. El truco aquí es que este estilo está desactivado, el Safari móvil pasa al desplazamiento normal y evita el rebote excesivo, por desgracia, no puede cancelar el arrastre continuo. Esta solución compleja también realiza un seguimiento, onscrollya que el rebote en la parte superior hace scrollTopque se pueda realizar un seguimiento negativo. Esta solución se probó en iOS 12.1.1 y tiene un inconveniente único: mientras se acelera el rebote único de desplazamiento, ya que restablecer el estilo puede no cancelarlo de inmediato.

function preventScrollVerticalBounceEffect(container) {
  setTouchScroll(true) //!: enable before the first scroll attempt

  container.addEventListener("touchstart", onTouchStart)
  container.addEventListener("touchmove", onTouch, { passive: false })
  container.addEventListener("touchend", onTouchEnd)
  container.addEventListener("scroll", onScroll)

  function isTouchScroll() {
    return !!container.style.webkitOverflowScrolling
  }

  let prevScrollTop = 0, prevTouchY, opid = 0

  function setTouchScroll(on) {
    container.style.webkitOverflowScrolling = on ? "touch" : null

    //Hint: auto-enabling after a small pause makes the start
    // smoothly accelerated as required. After the pause the
    // scroll position is settled, and there is no delta to
    // make over-bounce by dragging the finger. But still,
    // accelerated content makes short single over-bounce
    // as acceleration may not be off instantly.

    const xopid = ++opid
    !on && setTimeout(() => (xopid === opid) && setTouchScroll(true), 250)

    if(!on && container.scrollTop < 16)
      container.scrollTop = 0
    prevScrollTop = container.scrollTop
  }

  function isBounceOverTop() {
    const dY = container.scrollTop - prevScrollTop
    return dY < 0 && container.scrollTop < 16
  }

  function isBounceOverBottom(touchY) {
    const dY = touchY - prevTouchY

    //Hint: trying to bounce over the bottom, the finger moves
    // up the screen, thus Y becomes smaller. We prevent this.

    return dY < 0 && container.scrollHeight - 16 <=
      container.scrollTop + container.offsetHeight
  }

  function onTouchStart(e) {
    prevTouchY = e.touches[0].pageY
  }

  function onTouch(e) {
    const touchY = e.touches[0].pageY

    if(isBounceOverBottom(touchY)) {
      if(isTouchScroll())
        setTouchScroll(false)
      e.preventDefault()
    }

    prevTouchY = touchY
  }

  function onTouchEnd() {
    prevTouchY = undefined
  }

  function onScroll() {
    if(isTouchScroll() && isBounceOverTop()) {
      setTouchScroll(false)
    }
  }
}
Anton Baukin
fuente
1

respuesta mejorada @Ben Bos y comentada por @Tim

Este CSS ayudará a evitar problemas de desplazamiento y rendimiento con el renderizado CSS porque la posición cambió / poco retraso sin ancho y altura

body,
html {
  position: fixed;
  width: 100%; 
  height: 100%
}

auronsan zenx
fuente
En IOS13, esta es la solución más limpia para mí, y todavía no encontré inconvenientes ...
Soylent Graham
0

Para aquellos de ustedes que no desean deshacerse del rebote pero solo para saber cuándo se detiene (por ejemplo, para comenzar un cálculo de las distancias de la pantalla), pueden hacer lo siguiente (contenedor es el elemento contenedor que se desborda):

    const isBouncing = this.container.scrollTop < 0 ||
    this.container.scrollTop + this.container.offsetHeight >
        this.container.scrollHeight
Phil
fuente
0

Deshabilitar el efecto de desplazamiento de rebote de safari:

html,
body {
  height: 100%;
  width: 100%;
  overflow: auto;
  position: fixed;
}  
Abolfazl Baghshahi
fuente
-1

Al igual que el kiwi enojado, lo hice funcionar usando la altura en lugar de la posición:

html,body {
  height: 100%;
  overflow: hidden;
}

.the_element_that_you_want_to_have_scrolling{
  -webkit-overflow-scrolling: touch;
}
austinh7
fuente
como el documento esto permitirá el rebote también después de que el impulso no se desactive
CaSUaL
@CaSUaL ¿No estás seguro de lo que quieres decir? Esta solución funcionó para mi caso de uso ...
austinh7
-1

Solución probada, funciona en iOS 12.x

Este es el problema que estaba encontrando:

<body> <!-- the whole body can be scroll vertically -->
  <article>

    <my_gallery> <!-- some picture gallery, can be scroll horizontally -->
    </my_gallery>

  </article>
</body>

Mientras desplazo mi galería, el cuerpo siempre se desplaza a sí mismo (el deslizamiento humano no es realmente horizontal), lo que hace que mi galería sea inútil.

Esto es lo que hice mientras mi galería comienza a desplazarse

var html=jQuery('html');
html.css('overflow-y', 'hidden');
//above code works on mobile Chrome/Edge/Firefox
document.ontouchmove=function(e){e.preventDefault();} //Add this only for mobile Safari

Y cuando mi galería termina de desplazarse ...

var html=jQuery('html');
html.css('overflow-y', 'scroll');
document.ontouchmove=function(e){return true;}

Espero que esto ayude ~

RRTW
fuente