Deshabilite la opción de "zoom" de doble toque en el navegador en dispositivos táctiles

112

Quiero deshabilitar la funcionalidad de zoom de doble toque en elementos especificados en el navegador (en dispositivos táctiles), sin deshabilitar toda la funcionalidad de zoom .

Por ejemplo: un elemento se puede tocar varias veces para que suceda algo. Esto funciona bien en los navegadores de escritorio (como se esperaba), pero en los navegadores de dispositivos táctiles, se acercará.

Wouter Konecny
fuente
Aunque no para el zoom, aquí hay algunos otros esenciales: `-webkit-touch-callout: none; -webkit-text-size-ajuste: ninguno; -webkit-user-select: ninguno;
Udayraj Deshmukh

Respuestas:

99

Nota (a partir de 2020-08-04): esta solución no parece funcionar en iOS Safari v12 +. Actualizaré esta respuesta y eliminaré esta nota una vez que encuentre una solución clara que cubra iOS Safari.

Solución solo CSS

Agregue touch-action: manipulationa cualquier elemento en el que desee deshabilitar el zoom de doble toque, como con la siguiente disable-dbl-tap-zoomclase:

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

De los touch-actiondocumentos (el énfasis es mío):

manipulación

Habilite los gestos de zoom y paneo, pero deshabilite los gestos no estándar adicionales, como tocar dos veces para hacer zoom .

Este valor funciona en Android y en iOS.

Ross Allen
fuente
@SergoPasoevi, ¿puedes crear un ejemplo que no funcione? Estoy usando esta solución para iOS 12 y me está funcionando.
Ross Allen
Veo el mismo problema que @SergoPasoevi, no funciona en iOS 12
Trevor Jex
¡Funcionó para mí en iOS 12!
KB2497
2
¿Cuáles son las desventajas de envolver todo el cuerpo con la acción del tacto: manipulación?
oygen
1
No funciona en el último iOS al tocar dos veces una imagen.
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>

Lo he usado muy recientemente y funciona bien en iPad. No lo he probado en Android ni en otros dispositivos (porque el sitio web se mostrará solo en iPad).

Kablam
fuente
16
Eso deshabilitará TODAS las funciones de zoom, desafortunadamente esa no era mi pregunta. Quiero deshabilitar solo elementos especificados.
Wouter Konecny
Oi mierda. Lo leí al revés, fallaré. ¡Lo siento!
Kablam
5
¿Qué tal esta solución? Es solo para iOS, pero ¿quizás se puede modificar? : gist.github.com/2047491
Kablam
2
@WouterKonecny ​​Si quita la marca useragent, debería funcionar en cualquier dispositivo que admita el evento touchstart. Para detectar esos dispositivos, puede usar algo como isEventSupported
nxt
4
Apple ahora oficialmente ignora esto. github.com/w3c/html/issues/602
catamphetamine
38

Sé que esto puede ser antiguo, pero encontré una solución que funcionó perfectamente para mí. No es necesario utilizar metaetiquetas locas y detener el zoom del contenido.

No estoy 100% seguro de lo multidispositivo que es, pero funcionó exactamente como quería.

$('.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.
})

Esto simplemente deshabilitará la función de toque normal y luego volverá a llamar a un evento de clic estándar. Esto evita que el dispositivo móvil haga zoom, pero por lo demás funciona normalmente.

EDITAR: Esto ahora se ha probado y se está ejecutando en un par de aplicaciones en vivo. Parece ser 100% entre navegadores y plataformas. El código anterior debería funcionar como una solución de copiar y pegar en la mayoría de los casos, a menos que desee un comportamiento personalizado antes del evento de clic.

Rockster160
fuente
respuesta simple pero excelente. no es necesario modificar las metaetiquetas o etc.
benchpresser
2
esto deshabilita los clics, no creo que sea una buena solución, lo siento
Pixelomo
6
no necesita JS para hacer eso, simplemente puede configurar el atributo CSSpointer-events: none
Pixelomo
1
Gracias, esto funcionó perfectamente para manejar botones de incremento / decremento sin deshabilitar el zoom en toda la página.
Ramón
1
Si veo esto correctamente, esto podría fallar en ciertas situaciones en las que necesita eventos confiables (por ejemplo, hacer clic en algo que activa la pantalla completa u otros experimentos, como los eventos confiables yneed que significa ACTIVADO POR EL USUARIO / SO)
Manuel Graf
29

Solo quería responder a mi pregunta correctamente, ya que algunas personas no leen los comentarios debajo de una respuesta. Asi que aqui esta:

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

No escribí esto, solo lo modifiqué. Encontré la versión solo para iOS aquí: https://gist.github.com/2047491 (gracias Kablam)

Wouter Konecny
fuente
1
Esto no parece funcionar, al menos no en el SIII (con Android 4.0.4). Intenté enlazar al documento, cuerpo, ventana, *, sin dados.
Máximo
También me probé, funciona en safari / ipad, android chrome pero no con el navegador predeterminado de Android
Strae
2
jquery no es javascript, sería bueno tener un ejemplo de cómo hacer esto sin una biblioteca
Martijn Scheffer
Buscando una versión que no sea jquery :-(
Timo
de nuevo, jQuery no es javascript y no se debe fomentar, ya que no funciona bien con sitios basados ​​en ideas más modernas como angular. lea la pregunta
Martijn Scheffer
15

CSS para deshabilitar el zoom de doble toque globalmente (en cualquier elemento):

  * {
      touch-action: manipulation;
  }

manipulación

Habilite los gestos de zoom y paneo, pero deshabilite los gestos no estándar adicionales, como tocar dos veces para hacer zoom.

Gracias Ross, mi respuesta extiende la suya: https://stackoverflow.com/a/53236027/9986657

ene
fuente
1
Esto debe marcarse como la respuesta. Intenté ponerlo solo en html y body, pero no funcionó en iOS 13.2. Esto funciona.
R OMS
Esto no funciona en iOS 13 por sí solo, pero en conjunto con este código hace clic para hacer zoom para la aplicación React por completo. document.getElementById('root').addEventListener('click', () => {})
Sergei
Apple desactivado toca para hacer zoom en ios13, ¿cómo puedes decir que no funciona en iOS13?
oygen
15

Si necesita una versión que funcione sin jQuery , modifiqué la respuesta de Wouter Konecny (que también fue creada modificando esta esencia por Johan Sundström ) para usar 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();
}

Luego agregue un controlador de eventos touchstartque llame a esta función:

myButton.addEventListener('touchstart', preventZoom); 
Evrim Persembe
fuente
3
brillante. solo quería mencionar que necesitaba agregar un addEventListener para llamar a esto. myButton.addEventListener('touchstart', preventZoom);
martin jakubik
11

Debe establecer la propiedad CSS touch-actiona nonecomo se describe en esta otra respuesta https://stackoverflow.com/a/42288386/1128216

.disable-doubletap-to-zoom {
    touch-action: none;
}
Jonathan Morales Vélez
fuente
1
Esto funciona ... pero ¿qué pasa si quiero desactivar el zoom, pero dejar otros eventos táctiles? Tengo una mesa grande y esto también desactiva el desplazamiento.
FrenkyB
2
Si solo desea deshacerse del zoom de doble toque, debe establecer el valor en 'acción táctil: manipular;' Esto seguirá permitiendo la panorámica y el zoom. Nota importante: esto también ayuda a deshacerse de los navegadores de demora de clic introducidos para implementar el zoom de doble toque. ver developer.mozilla.org/en-US/docs/Web/CSS/touch-action
cschuff
¿En qué etiqueta HTML se debe agregar esta clase?
Razvan Zamfir
Creo que puede agregarlo a cualquier elemento en el que no desee que el uso se acerque. Por ejemplo, en mi caso, no quería que el usuario hiciera zoom en ninguna parte de mi página, así que lo agregué a la etiqueta del cuerpo.
Jonathan Morales Vélez
2
* {
    -ms-touch-action: manipulation;
    touch-action: manipulation;
}

Desactive el doble toque para hacer zoom en las pantallas táctiles. Explorador de Internet incluido.

Erçin Dedeoğlu
fuente
1

Simplemente evite el comportamiento predeterminado de click, dblclicko los touchendeventos deshabilitarán la funcionalidad de zoom.

Si ya tiene una devolución de llamada en uno de estos eventos, simplemente llame a event.preventDefault().

William Grasel
fuente
1
Esto funcionó para mí. Estaba definiendo mi propio evento de inicio táctil en un botón y quería desactivar la función de zoom.
Rick Giuly
1

Si hay alguien como yo que está experimentando este problema con Vue.js , simplemente agregar .prevent hará el truco:@click.prevent="someAction"

Sølve Tornøe
fuente
0

Esto evitará el zoom de doble toque en los elementos en 'cuerpo', esto se puede cambiar a cualquier otro selector

$('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');

});

Pero esto también evitó que mi evento de clic se activara cuando se hacía clic varias veces, así que tuve que vincular otro evento para activar los eventos en varios 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.
    }
});

En touchstart agregué el código para evitar el zoom y activar 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
fuente
-1

Supongo que tengo un <div>área de contenedor de entrada con texto, controles deslizantes y botones, y quiero inhibir los toques dobles accidentales en eso <div>. Lo siguiente no inhibe el zoom en el área de entrada y no se relaciona con el doble toque y el zoom fuera de mi <div>área. Existen variaciones según la aplicación del navegador.

Solo lo probé.

(1) Para Safari en iOS y Chrome en Android, y es el método preferido. Funciona excepto para la aplicación de Internet en Samsung, donde deshabilita los toques dobles no en el total <div>, sino al menos en los elementos que manejan toques. Vuelve return false, con excepción de texty rangeentradas.

$('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) Opcionalmente para la aplicación de Internet incorporada en Android (5.1, Samsung), inhibe los toques dobles en <div>, pero inhibe el zoom en <div>:

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

(3) Para Chrome en Android 5.1, deshabilita el doble toque, no inhibe el zoom y no hace nada sobre el doble toque en los otros navegadores. La inhibición del doble toque <meta name="viewport" ...>es irritante, porque <meta name="viewport" ...>parece una buena práctica.

<meta name="viewport" content="width=device-width, initial-scale=1, 
          maximum-scale=5, user-scalable=yes">
Pedro
fuente
-4

Aquí vamos

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

no estoy seguro
fuente