Désactivez l'option "zoomer" en appuyant deux fois dans le navigateur sur les appareils tactiles

112

Je souhaite désactiver la fonctionnalité de zoom double-tap sur des éléments spécifiés dans le navigateur (sur les appareils tactiles), sans désactiver toutes les fonctionnalités de zoom .

Par exemple: un élément peut être touché plusieurs fois pour que quelque chose se produise. Cela fonctionne bien sur les navigateurs de bureau (comme prévu), mais sur les navigateurs d'appareils tactiles, il effectuera un zoom avant.

Wouter Konecny
la source
Bien que pas pour le zoom, mais en voici quelques autres essentiels - `-webkit-touch-callout: none; -webkit-text-size-Adjust: aucun; -webkit-user-select: aucun;
Udayraj Deshmukh

Réponses:

99

Remarque (à partir du 04/08/2020): cette solution ne semble pas fonctionner dans iOS Safari v12 +. Je mettrai à jour cette réponse et supprimerai cette note une fois que je trouverai une solution claire qui couvre iOS Safari.

Solution uniquement CSS

Ajoutez touch-action: manipulationà n'importe quel élément sur lequel vous souhaitez désactiver le zoom double tap, comme avec la disable-dbl-tap-zoomclasse suivante :

.disable-dbl-tap-zoom {
  touch-action: manipulation;
}

Extrait des touch-actiondocuments (c'est moi qui souligne):

manipulation

Activez les gestes de panoramique et de zoom par pincement, mais désactivez les gestes non standard supplémentaires tels que le double-appui pour zoomer .

Cette valeur fonctionne sur Android et sur iOS.

Ross Allen
la source
@SergoPasoevi, pouvez-vous créer un exemple qui ne fonctionne pas? J'utilise cette solution pour iOS 12 et cela fonctionne pour moi.
Ross Allen
Je vois le même problème que @SergoPasoevi, ne fonctionne pas sur iOS 12
Trevor Jex
A travaillé pour moi sur iOS 12!
KB2497
2
Quels sont les inconvénients d'envelopper tout votre corps avec l'action tactile: la manipulation?
oygen le
1
Ne fonctionne pas sur le dernier iOS lorsque vous appuyez deux fois sur une image.
Adam Silver
54
<head>
<title>Site</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"> 
etc...
</head>

Je l'ai utilisé très récemment et cela fonctionne très bien sur iPad. Je n'ai pas testé sur Android ou d'autres appareils (car le site Web sera affiché sur iPad uniquement).

Kablam
la source
16
Cela désactivera TOUTES les fonctionnalités de zoom, malheureusement ce n'était pas ma question. Je souhaite désactiver uniquement les éléments spécifiés.
Wouter Konecny
Oh merde. Je l'ai lu dans l'autre sens, l'échec est sur moi. Désolé!
Kablam
5
Et cette solution? C'est iOS uniquement, mais peut-être modifiable? : gist.github.com/2047491
Kablam
2
@WouterKonecny ​​Si vous supprimez le contrôle useragent, il devrait fonctionner sur tout périphérique prenant en charge l'événement touchstart. Pour détecter ces appareils, vous pouvez utiliser quelque chose comme isEventSupported
nxt
4
Apple ignore maintenant officiellement cela. github.com/w3c/html/issues/602
catamphétamine
38

Je sais que cela peut être vieux, mais j'ai trouvé une solution qui fonctionnait parfaitement pour moi. Pas besoin de balises méta folles et d'arrêter le zoom sur le contenu.

Je ne sais pas à 100% à quel point c'est multi-appareil, mais cela a fonctionné exactement comme je le voulais.

$('.no-zoom').bind('touchend', function(e) {
  e.preventDefault();
  // Add your code here. 
  $(this).click();
  // This line still calls the standard click event, in case the user needs to interact with the element that is being clicked on, but still avoids zooming in cases of double clicking.
})

Cela désactivera simplement la fonction de tapotement normale, puis appellera à nouveau un événement de clic standard. Cela empêche l'appareil mobile de zoomer, mais fonctionne autrement normalement.

EDIT: Cela a maintenant été testé dans le temps et fonctionne dans quelques applications en direct. Semble être 100% multi-navigateur et plateforme. Le code ci-dessus doit fonctionner comme une solution de copier-coller dans la plupart des cas, sauf si vous souhaitez un comportement personnalisé avant l'événement de clic.

Rockster160
la source
réponse simple mais excellente. pas besoin de modifier les balises meta ou etc.
benchpresser
2
cela désactive les clics, je ne pense pas que ce soit une bonne solution désolé
Pixelomo
6
vous n'avez pas besoin de JS pour faire cela, vous pouvez simplement définir l'attribut CSSpointer-events: none
Pixelomo
1
Merci cela a parfaitement fonctionné pour gérer les boutons d'incrémentation / décrémentation sans désactiver le zoom sur toute la page.
Ramón
1
Si je vois cela correctement, cela peut échouer dans certaines situations où vous avez besoin d'événements de confiance (par exemple, cliquer sur qc qui déclenche le plein écran ou d'autres expériences, comme les événements de confiance yneed, ce qui signifie DÉCLENCHÉ PAR L'UTILISATEUR / OS)
Manuel Graf
29

Je voulais juste répondre correctement à ma question car certaines personnes ne lisent pas les commentaires ci-dessous une réponse. Alors voilà:

(function($) {
  $.fn.nodoubletapzoom = function() {
      $(this).bind('touchstart', function preventZoom(e) {
        var t2 = e.timeStamp
          , t1 = $(this).data('lastTouch') || t2
          , dt = t2 - t1
          , fingers = e.originalEvent.touches.length;
        $(this).data('lastTouch', t2);
        if (!dt || dt > 500 || fingers > 1) return; // not double-tap

        e.preventDefault(); // double tap - prevent the zoom
        // also synthesize click events we just swallowed up
        $(this).trigger('click').trigger('click');
      });
  };
})(jQuery);

Je n'ai pas écrit ceci, je l'ai juste modifié. J'ai trouvé la version iOS uniquement ici: https://gist.github.com/2047491 (merci Kablam)

Wouter Konecny
la source
1
Cela ne semble pas fonctionner, du moins pas sur le SIII (avec Android 4.0.4). J'ai essayé de relier à document, corps, fenêtre, *, pas de dés.
Max
M'a essayé aussi, fonctionne sur safari / ipad, Android Chrome mais pas avec le navigateur par défaut Android
Strae
2
jquery n'est pas du javascript, ce serait bien d'avoir un exemple de comment faire cela sans bibliothèque
Martijn Scheffer
Vous recherchez une version non-jquery :-(
Timo
encore une fois, jQuery n'est pas du javascript et ne devrait pas être encouragé, car il ne fonctionne pas bien avec des sites basés sur des idées plus modernes comme angular. lire la question
Martijn Scheffer
15

CSS pour désactiver globalement le zoom double-tap (sur n'importe quel élément):

  * {
      touch-action: manipulation;
  }

manipulation

Activez les gestes de panoramique et de zoom par pincement, mais désactivez les gestes non standard supplémentaires tels que le double-appui pour zoomer.

Merci Ross, ma réponse étend la sienne: https://stackoverflow.com/a/53236027/9986657

Jan
la source
1
Cela devrait être marqué comme la réponse. J'ai essayé de le mettre uniquement sur html et body mais cela ne fonctionnait pas sous iOS 13.2. Cela marche.
R OMS
Cela ne fonctionne pas sur iOS 13 en soi, mais en conjonction avec ce code, il bloque le robinet pour zoomer complètement pour l'application React. document.getElementById('root').addEventListener('click', () => {})
Sergei
apple désactivé appuyez pour zoomer sur ios13, comment pouvez-vous dire que cela ne fonctionne pas sur iOS13?
oygen
15

Si vous avez besoin d'une version qui fonctionne sans jQuery , j'ai modifié la réponse de Wouter Konecny (qui a également été créée en modifiant cet essentiel par Johan Sundström ) pour utiliser du JavaScript vanilla.

function preventZoom(e) {
  var t2 = e.timeStamp;
  var t1 = e.currentTarget.dataset.lastTouch || t2;
  var dt = t2 - t1;
  var fingers = e.touches.length;
  e.currentTarget.dataset.lastTouch = t2;

  if (!dt || dt > 500 || fingers > 1) return; // not double-tap

  e.preventDefault();
  e.target.click();
}

Ajoutez ensuite un gestionnaire d'événements sur touchstartqui appelle cette fonction:

myButton.addEventListener('touchstart', preventZoom); 
Evrim Persembe
la source
3
brillant. je voulais juste mentionner que je devais ajouter un addEventListener pour appeler cela. myButton.addEventListener('touchstart', preventZoom);
martin jakubik
11

Vous devez définir la propriété css touch-actionsur nonecomme décrit dans cette autre réponse https://stackoverflow.com/a/42288386/1128216

.disable-doubletap-to-zoom {
    touch-action: none;
}
Jonathan Morales Vélez
la source
1
Cela fonctionne ... mais que faire si je veux désactiver le zoom, mais laisser d'autres événements tactiles? J'ai une grande table et cela désactive également le défilement.
FrenkyB
2
Si vous souhaitez uniquement vous débarrasser du zoom à double pression, vous devez définir la valeur sur 'touch-action: manipulate;' Cela permettra toujours le panoramique et le zoom par pincement. Remarque importante: Cela permet également de se débarrasser des navigateurs de délai de clic introduits pour implémenter le zoom double-tap. voir developer.mozilla.org/en-US/docs/Web/CSS/touch-action
cschuff
Sur quelle balise HTML cette classe doit-elle être ajoutée?
Razvan Zamfir
Je pense que vous pouvez simplement l'ajouter à n'importe quel élément sur lequel vous ne voulez pas que l'utilisation zoome. Par exemple, dans mon cas, je ne voulais pas que l'utilisateur effectue un zoom sur une partie de ma page, je l'ai donc ajouté à la balise body.
Jonathan Morales Vélez
2
* {
    -ms-touch-action: manipulation;
    touch-action: manipulation;
}

Désactivez le double tap pour zoomer sur les écrans tactiles. Internet Explorer inclus.

Erçin Dedeoğlu
la source
1

Simple empêche le comportement par défaut de click, dblclickou les touchendévénements désactiveront la fonctionnalité de zoom.

Si vous avez déjà un rappel sur l'un de ces événements, appelez simplement un event.preventDefault().

William Grasel
la source
1
Cela a fonctionné pour moi. Je définissais mon propre événement touchstart sur un bouton et je voulais désactiver la fonction de zoom.
Rick Giuly
1

S'il y a quelqu'un comme moi qui rencontre ce problème avec Vue.js , ajouter simplement .prevent fera l'affaire:@click.prevent="someAction"

Sølve Tornøe
la source
0

Cela empêchera un double tap zoom sur les éléments dans `` corps '', cela peut être changé en n'importe quel autre sélecteur

$('body').bind('touchstart', function preventZoom(e){
            var t2 = e.timeStamp;
            var t1 = $(this).data('lastTouch') || t2;
            var dt = t2 - t1;
            var fingers = e.originalEvent.touches.length;
            $(this).data('lastTouch', t2);
            if (!dt || dt > 500 || fingers > 1){
                return; // not double-tap
            }
            e.preventDefault(); // double tap - prevent the zoom
            // also synthesize click events we just swallowed up
            $(e.target).trigger('click');

});

Mais cela a également empêché mon événement de clic de se déclencher lorsque j'ai cliqué plusieurs fois, j'ai donc dû lier un autre événement pour déclencher les événements sur plusieurs clics.

$('.selector').bind('touchstart click', preventZoom(e) {    
    e.stopPropagation(); //stops propagation
    if(e.type == "touchstart") {
      // Handle touchstart event.
    } else if(e.type == "click") {
      // Handle click event.
    }
});

Sur touchstart, j'ai ajouté le code pour empêcher le zoom et déclencher un clic.

$('.selector').bind('touchstart, click', function preventZoom(e){
            e.stopPropagation(); //stops propagation
            if(e.type == "touchstart") {
                // Handle touchstart event.
                var t2 = e.timeStamp;
                var t1 = $(this).data('lastTouch') || t2;
                var dt = t2 - t1;
                var fingers = e.originalEvent.touches.length;
                $(this).data('lastTouch', t2);


                if (!dt || dt > 500 || fingers > 1){
                    return; // not double-tap
                }

                e.preventDefault(); // double tap - prevent the zoom
                // also synthesize click events we just swallowed up
                $(e.target).trigger('click');

            } else if(e.type == "click") {
                // Handle click event.
               "Put your events for click and touchstart here"
            }

 });
Dally S
la source
-1

Je suppose que j'ai une <div>zone de conteneur d'entrée avec du texte, des curseurs et des boutons, et que je souhaite empêcher les doubles-taps accidentels <div>. Ce qui suit n'empêche pas le zoom sur la zone de saisie et ne concerne pas le double-tap et le zoom en dehors de ma <div>zone. Il existe des variations en fonction de l'application du navigateur.

J'ai juste essayé.

(1) Pour Safari sur iOS et Chrome sur Android, c'est la méthode préférée. Fonctionne sauf pour l'application Internet sur Samsung, où elle désactive les doubles-taps non pas sur le plein <div>, mais au moins sur les éléments qui gèrent les taps. Il retourne return false, à l'exception des entrées textet range.

$('selector of <div> input area').on('touchend',disabledoubletap);

function disabledoubletap(ev) {

    var preventok=$(ev.target).is('input[type=text],input[type=range]');

    if(preventok==false) return false; 
}

(2) En option pour l'application Internet intégrée sur Android (5.1, Samsung), empêche les doubles tapotements sur <div>, mais empêche le zoom sur <div>:

$('selector of <div> input area').on('touchstart touchend',disabledoubletap);

(3) Pour Chrome sur Android 5.1, désactive du tout le double-tap, n'interdit pas le zoom et ne fait rien pour le double-tap dans les autres navigateurs. L'inhibition du double tap sur <meta name="viewport" ...>est irritante, car <meta name="viewport" ...>semble être une bonne pratique.

<meta name="viewport" content="width=device-width, initial-scale=1, 
          maximum-scale=5, user-scalable=yes">
Peter
la source
-2

Utilisation des événements tactiles CSS: aucun Supprime complètement tous les événements tactiles. Le simple fait de laisser ceci ici au cas où quelqu'un aurait également ce problème, m'a pris 2 heures pour trouver cette solution et ce n'est qu'une ligne de css. https://developer.mozilla.org/en-US/docs/Web/CSS/touch-action

Ásgeir Frímannsson
la source
-4

Et c'est parti

<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">

pas certain
la source