47 votes

document.ontouchmove et défilement sur iOS 5

IOS 5 a apporté un certain nombre d'améliorations à JavaScript et aux applications Web. L'une d'elles est l'amélioration du défilement. Si vous ajoutez

-webkit-overflow-scroll:touch;

au style d'un élément textarea, le défilement fonctionnera bien avec un seul doigt.

Mais il y a un problème. Pour empêcher le défilement de tout l'écran, il est recommandé aux applications web d'ajouter cette ligne de code :

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

Toutefois, cela désactive le nouveau défilement.

Quelqu'un a-t-il un moyen agréable d'autoriser le nouveau défilement à l'intérieur d'une zone de texte, mais sans autoriser le défilement de l'ensemble du formulaire ?

0 votes

Vous pourriez essayer yourScrollElement.ontouchmove=function(e) {e.preventDefault()} ; Je ne sais pas si cela fonctionne.

1 votes

Non - cela ne fonctionne pas. Merci !

0 votes

Il doit y avoir une certaine confusion, car la suggestion de Gerben est exactement la même que la suggestion alternative de Brian Nickel ci-dessous.

56voto

Brian Nickel Points 8687

Mise à jour Par Commentaire d'Alvaro si cette solution ne fonctionne plus à partir d'iOS 11.3.

Vous devriez pouvoir autoriser le défilement en choisissant si preventDefault est appelé ou non. Par exemple,

document.ontouchmove = function(e) {
    var target = e.currentTarget;
    while(target) {
        if(checkIfElementShouldScroll(target))
            return;
        target = target.parentNode;
    }

    e.preventDefault();
};

Il est également possible d'empêcher l'événement d'atteindre le niveau du document.

elementYouWantToScroll.ontouchmove = function(e) {
    e.stopPropagation();
};

Modifier Pour ceux qui lisent plus tard, l'autre réponse fonctionne et est beaucoup plus facile.

0 votes

Une solution simple et efficace. Solution alternative au plugin jquery hakoniemi.net/labs/nonbounce

0 votes

Je crois que vous devriez utiliser e.target pas e.currentTarget comme e.currentTarget fera toujours référence à l'élément auquel l'écouteur est attaché, dans ce cas-ci document .

0 votes

@Alvaro avez-vous trouvé une solution ?

23voto

1nfiniti Points 884

Le seul problème avec la réponse de Brian Nickel est que (comme l'utilisateur1012566 l'a mentionné) stopPropagation n'empêche pas la formation de bulles lorsque vous atteignez les limites de votre scrollable. Vous pouvez empêcher cela en procédant comme suit :

elem.addEventListener('touchstart', function(event){
    this.allowUp = (this.scrollTop > 0);
    this.allowDown = (this.scrollTop < this.scrollHeight - this.clientHeight);
    this.prevTop = null; 
    this.prevBot = null;
    this.lastY = event.pageY;
});

elem.addEventListener('touchmove', function(event){
    var up = (event.pageY > this.lastY), 
        down = !up;

    this.lastY = event.pageY;

    if ((up && this.allowUp) || (down && this.allowDown)) 
        event.stopPropagation();
    else 
        event.preventDefault();
});

0 votes

Je n'ai pas réussi à le faire fonctionner sur IOS6 et il empêche le défilement sur les navigateurs PC. Sur IOS, il n'empêche le défilement élastique que si vous avez déjà dépassé les limites une fois.

3 votes

Cette solution ne semble pas fonctionner. Lorsque le défilement atteint sa limite supérieure ou inférieure, l'élément se fige simplement à sa position actuelle, de sorte que je ne peux pas faire défiler dans les deux sens. J'utilise iOS 7.1.

0 votes

Oui, exactement ce qu'il a dit^

16voto

Andrew Plummer Points 412

Pour tous ceux qui essaient d'obtenir ce résultat avec PhoneGap, vous pouvez désactiver le défilement élastique dans le champ cordova.plist fixer la valeur de UIWebViewBounce à NO . J'espère que cela aidera les personnes qui passent des heures sur ce sujet (comme moi).

1 votes

Merci, Andrew ! Je n'ai eu qu'à passer une demi-heure à chercher ça !

0 votes

Merci ! Ça m'a fait gagner un tas de temps à chasser les fantômes !

0 votes

Options supplémentaires/documentation à ce sujet : tripleshotsoftware.blogspot.com/2012/09/

7voto

vladaman Points 1506

ScrollFix semble être la solution idéale. Je l'ai testé et il fonctionne comme un charme !

https://github.com/joelambert/ScrollFix

/**
 * ScrollFix v0.1
 * http://www.joelambert.co.uk
 *
 * Copyright 2011, Joe Lambert.
 * Free to use under the MIT license.
 * http://www.opensource.org/licenses/mit-license.php
 */

var ScrollFix = function(elem) {
    // Variables to track inputs
    var startY, startTopScroll;

    elem = elem || document.querySelector(elem);

    // If there is no element, then do nothing  
    if(!elem)
        return;

    // Handle the start of interactions
    elem.addEventListener('touchstart', function(event){
        startY = event.touches[0].pageY;
        startTopScroll = elem.scrollTop;

        if(startTopScroll <= 0)
            elem.scrollTop = 1;

        if(startTopScroll + elem.offsetHeight >= elem.scrollHeight)
            elem.scrollTop = elem.scrollHeight - elem.offsetHeight - 1;
    }, false);
};

2voto

user1012566 Points 216

Il était frustrant de découvrir un problème connu avec stopPropagation et le défilement natif des divs. Il ne semble pas empêcher le onTouchMove de rebondir, de sorte que lors du défilement au-delà des limites de la div (vers le haut en haut ou vers le bas en bas), la page entière rebondit.

Plus de discussion aquí y aquí .

0 votes

Pour info, vous pouvez éviter ce problème en appliquant la solution indiquée ci-dessous.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X