web-dev-qa-db-fra.com

Impossible d'empêcher `touchmove` de faire défiler la fenêtre sur iOS

Nous essayons de faire défiler un élément de notre application Web iOS tout en empêchant le défilement de la fenêtre elle-même. Nous capturons l'événement touchmove dans la fenêtre, défilons l'élément par programme et (essayons) d'empêcher le défilement de la fenêtre elle-même en appelant preventDefault pour l'événement.

Malheureusement, cela ne fonctionne pas dans Mobile Safari. La fenêtre continue de défiler sous notre élément. Le problème ressemble exactement au bogue Webkit décrit dans https://bugs.webkit.org/show_bug.cgi?id=163207 , mais ce problème était censé avoir été résolu dans iOS 10.3 alors que j'exécute 11.3.

Capturer touchforcestart et appeler preventDefault semble empêcher le défilement de la fenêtre, mais nous l’appelons dans touchstart, ce qui semble être "trop ​​tard" car la fenêtre défile toujours . Le défilement n'est empêché que la prochaine fois que touchstart sera appelé.

Des idées sur ce qui se passe? Nous sommes déroutés car il s'agit clairement d'un bogue, mais il semble avoir été corrigé il y a quelque temps.

24
Matthew Gertner

J'ai récemment rencontré ce même problème. Vous devrez passer { passive: false } lors de l’enregistrement de l’écouteur d’événements touchmove. par exemple.

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

En effet, les écouteurs d'événements tactiles de document sont désormais passifs par défaut dans Safari 11.1, qui est fourni avec iOS 11.3. Cette modification est documentée dans Safari 11.1 notes de version :

API Web

  • [...]
  • Les écouteurs d'événements tactiles de documents racine mis à jour pour utiliser le mode passif améliorent les performances de défilement et réduisent le nombre d'accidents.
60
user9576791

Vous devez lier preventDefault à deux événements: touchmove et touchforcechange pour que cela fonctionne dans ios 11, par exemple.

document.addEventListener('touchmove', this.preventDefault, {passive: false});
document.addEventListener('touchforcechange', this.preventDefault, {passive: false});

et vous devriez les lier avant touchstart

Si vous les liez dans votre gestionnaire touchstart ou dragStart, ils ne peuvent empêcher le défilement lors du prochain glissement.

2
User007