web-dev-qa-db-fra.com

ipad safari: désactiver le défilement et l'effet de rebond?

Je travaille sur une application basée sur un navigateur. Actuellement, je développe et stylise le navigateur ipad safari.

Je cherche deux choses sur l'ipad: comment désactiver le défilement vertical pour les pages qui n'en ont pas besoin? & comment puis-je désactiver l'effet de rebond élastique?

112
Adam

Cette réponse n'est plus applicable, sauf si vous développez pour un très vieil appareil iOS ... Voir d'autres solutions


Réponse 2011: pour une application Web/html exécutée dans iOS Safari, vous voulez quelque chose comme

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

Pour iOS 5, vous voudrez peut-être prendre en compte les éléments suivants: document.ontouchmove et défilement sur iOS 5

Mise à jour de septembre 2014: une approche plus approfondie peut être trouvée ici: https://github.com/luster-io/prevent-overscroll . Pour cela et de nombreux conseils utiles sur l'application Web, voir http://www.luster.io/blog/9-29-14-mobile-web-checklist.html

Mise à jour de mars 2016: ce dernier lien n'est plus actif - voir https://web.archive.org/web/20151103001838/http://www.luster.io/blog/9-29-14-mobile -web-checklist.html pour la version archivée. Merci @falsarella pour l'avoir signalé.

155
Oskar Austegard

Vous pouvez aussi changer la position du body/html en fixed:

body,
html {
  position: fixed;
}
97
Ben Bos

Pour empêcher le défilement sur les navigateurs mobiles modernes, vous devez ajouter le passif: false. J'avais tiré les cheveux pour que cela fonctionne jusqu'à ce que je trouve cette solution. Je n'ai trouvé cela mentionné qu'à un autre endroit sur Internet.

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

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

Vous pouvez utiliser cet extrait de code jQuery pour cela:

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

Cela bloquera le défilement vertical ainsi que tout effet de rebond se produisant sur vos pages.

7
overflow: scroll;
-webkit-overflow-scrolling: touch;

Sur le conteneur, vous pouvez définir l'effet de rebond à l'intérieur de l'élément

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

4
user956584

Je sais que cela est légèrement hors piste, mais je me suis servi de Swiffy pour convertir Flash en un jeu interactif HTML5 et je suis tombé sur le même problème de défilement, mais je n’ai trouvé aucune solution qui fonctionne.

Le problème que j’avais, c’est que la scène Swiffy occupait tout l’écran. Ainsi, dès qu’elle a été chargée, l’événement Touchmove du document n’a jamais été déclenché.

Si j'essayais d'ajouter le même événement au conteneur Swiffy, il était remplacé dès que la scène avait été chargée.

En fin de compte, je l'ai résolu (plutôt en désordre) en appliquant l'événement touchmove à chaque DIV de la scène. Comme ces divs étaient également en constante évolution, je devais continuer à les vérifier.

C'était ma solution, qui semble bien fonctionner. J'espère que cela sera utile à quiconque essaiera de trouver la même solution que moi.

var divInterval = setInterval(updateDivs,50);
function updateDivs(){
$("#swiffycontainer > div").bind(
    'touchmove',
     function(e) {
        e.preventDefault();
    }
);}
4
Tom

aucune des solutions ne fonctionne pour moi. C'est comme ça que je le fais.

  html,body {
      position: fixed;
      overflow: hidden;
    }
  .the_element_that_you_want_to_have_scrolling{
      -webkit-overflow-scrolling: touch;
  }
2
angry kiwi

Testé dans l'iphone. Il suffit d’utiliser ce conteneur d’éléments css sur la cible pour modifier le comportement de défilement, qui s’arrête lorsque le doigt quitte l’écran.

-webkit-overflow-scrolling: auto

https://developer.mozilla.org/en-US/docs/Web/CSS/-webkit-overflow-scrolling

2
user1021364

Essayez cette JS sollutuion :

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

Empêche le défilement par défaut de Safari et les gestes de rebond sans détacher vos écouteurs d'événements tactiles.

2
Andrii Verbytskyi

Pour ceux qui utilisent Web App MyScript et qui luttent avec le défilement du corps/glisser (sur iPad et tablettes) au lieu d'écrire réellement:

<body touch-action="none" unresolved>

Cela a réglé le problème pour moi.

1
Miro

Vous pouvez utiliser js pour empêcher le défilement:

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

Et que de simplement courir/arrêter toggleScrollfonctionner lorsque vous ouvrez/fermez modal.

Comme ceci toggleScroll(true) / toggleScroll(false)

(Ceci est uniquement pour iOS, sur Android ne fonctionne pas)

1
Vlad Novikov

Essayez cette solution JS qui bascule le style webkitOverflowScrolling. Le truc ici, c’est que ce style est désactivé, le Safari mobile va au défilement ordinaire et empêche le rebond excessif - hélas, il n’est pas en mesure d’annuler le glisser en cours. Cette solution complexe suit également onscroll car le rebond par-dessus rend scrollTop négatif qui peut être suivi. Cette solution a été testée sur iOS 12.1.1 et présente un seul inconvénient: lors de l’accélération du survol simple du défilement, la réinitialisation du style ne l’annule pas immédiatement.

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)
    }
  }
}
1
Anton Baukin

Solution testée, fonctionne sur iOS 12.x

C'est le problème que je rencontrais:

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

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

  </article>
</body>

Pendant que je fais défiler ma galerie, le corps défilant toujours lui-même (les balayages humains ne sont pas vraiment horizontaux), cela rend ma galerie inutile.

Voici ce que j'ai fait pendant que ma galerie commence à défiler

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

Et quand ma galerie termine son défilement ...

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

J'espère que cela aide ~

0
RRTW

Code to Pour supprimer ipad safari: désactivez le défilement et l'effet de rebond

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

Si vous avez la balise canvas dans le document, cela affectera parfois la facilité d'utilisation de l'objet dans Canvas (exemple: mouvement de l'objet); alors ajoutez le code ci-dessous pour le réparer.

    document.getElementById("canvasId").addEventListener("touchmove", function (e) {
        e.stopPropagation();
    }, { passive: false });
0
Teju V B

réponse améliorée @Ben Bos et commentée par @Tim

Ce css aidera à éviter les problèmes de défilement et de performances lors du rendu de css car la position a été modifiée/peu en retard sans largeur ni hauteur.

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

0
auronsan zenx