Desative a opção "zoom" de toque duplo no navegador em dispositivos de toque

112

Desejo desativar a funcionalidade de zoom de toque duplo em elementos especificados no navegador (em dispositivos de toque), sem desativar toda a funcionalidade de zoom .

Por exemplo: Um elemento pode ser tocado várias vezes para que algo aconteça. Isso funciona bem em navegadores de desktop (como esperado), mas em navegadores de dispositivos sensíveis ao toque, aumentará o zoom.

Wouter Konecny
fonte
Embora não seja para zoom, aqui estão alguns outros essenciais - `-webkit-touch-callout: nenhum; -webkit-text-size-ajustar: nenhum; -webkit-user-select: nenhum;
Udayraj Deshmukh

Respostas:

98

Observação (a partir de 2020-08-04): esta solução não parece funcionar no iOS Safari v12 +. Vou atualizar esta resposta e excluir esta observação assim que encontrar uma solução clara que cubra o iOS Safari.

Solução somente CSS

Adicione touch-action: manipulationa qualquer elemento em que deseja desativar o zoom de toque duplo, como com a seguinte disable-dbl-tap-zoomclasse:

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

Dos touch-actiondocumentos (grifo meu):

manipulação

Ative os gestos de panorâmica e de zoom, mas desative os gestos não padrão adicionais, como tocar duas vezes para ampliar .

Este valor funciona no Android e no iOS.

Ross Allen
fonte
@SergoPasoevi, você pode criar um exemplo que não funcione? Estou usando esta solução para iOS 12 e está funcionando para mim.
Ross Allen de
Eu vejo o mesmo problema que @SergoPasoevi, não funciona no iOS 12
Trevor Jex
Funcionou para mim no iOS 12!
KB2497
2
quais são as desvantagens de envolver todo o seu corpo com ação de toque: manipulação?
oxigênio
1
Não funciona no iOS mais recente ao tocar duas vezes em uma imagem.
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>

Usei-o recentemente e funciona bem no iPad. Não testei no Android ou outros dispositivos (porque o site será exibido apenas no iPad).

Kablam
fonte
16
Isso desabilitará TODAS as funcionalidades de zoom, infelizmente essa não foi a minha dúvida. Eu quero desabilitar apenas elementos especificados.
Wouter Konecny
Oi merda. Eu li ao contrário, falha em mim. Desculpe!
Kablam
5
Que tal essa solução? É apenas iOS, mas talvez possa ser ajustado? : gist.github.com/2047491
Kablam
2
@WouterKonecny ​​Se você remover o useragent, verifique se ele deve funcionar em qualquer dispositivo que suporte o evento touchstart. Para detectar esses dispositivos, você pode usar algo como isEventSupported
nxt
4
A Apple agora oficialmente ignora isso. github.com/w3c/html/issues/602
catanfetamina
38

Eu sei que isso pode ser antigo, mas encontrei uma solução que funcionou perfeitamente para mim. Não há necessidade de meta tags malucas e parar de ampliar o conteúdo.

Não tenho 100% de certeza de como é cross-device, mas funcionou exatamente como eu queria.

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

Isso simplesmente desativará a função de toque normal e, em seguida, chamará um evento de clique padrão novamente. Isso evita que o dispositivo móvel aplique zoom, mas funciona normalmente.

EDIT: Isso agora foi testado pelo tempo e rodando em alguns aplicativos ativos. Parece ser 100% cross-browser e plataforma. O código acima deve funcionar como uma solução de copiar e colar na maioria dos casos, a menos que você queira um comportamento personalizado antes do evento de clique.

Rockster160
fonte
resposta simples, mas ótima. não há necessidade de modificar meta tags ou etc.
benchpresser de
2
isso desativa os cliques, não acho que seja uma boa solução, desculpe
Pixelomo 01 de
6
você não precisa de JS para fazer isso, você pode apenas definir o atributo CSSpointer-events: none
Pixelomo
1
Obrigado, isso funcionou perfeitamente para lidar com botões de incremento / decremento sem desativar o zoom em toda a página.
Ramón
1
Se eu ver isso corretamente, isso pode falhar em certas situações em que você precisa de eventos confiáveis ​​(por exemplo, clicar em sth que está acionando a tela inteira ou outros experimentais, como os eventos confiáveis ​​yneed que significa DESENCADEADO PELO USUÁRIO / SO)
Manuel Graf
29

Eu só queria responder minha pergunta adequadamente, pois algumas pessoas não leem os comentários abaixo de uma resposta. Então aqui está:

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

Eu não escrevi isso, apenas modifiquei. Encontrei a versão exclusiva para iOS aqui: https://gist.github.com/2047491 (obrigado Kablam)

Wouter Konecny
fonte
1
Isso não parece funcionar, pelo menos não no SIII (c / Android 4.0.4). Tentei vincular a documento, corpo, janela, *, sem dados.
Máx.
Testou-me também, funciona em safari / ipad, android chrome, mas não com o navegador padrão Android
Strae
2
jquery não é javascript, seria bom ter um exemplo de como fazer isso sem uma biblioteca
Martijn Scheffer
Procurando por uma versão não jquery :-(
Timo
novamente, jQuery não é javascript e não deve ser incentivado, pois não funciona bem com sites baseados em ideias mais modernas como o angular. leia a pergunta
Martijn Scheffer
15

CSS para desativar o zoom de toque duplo globalmente (em qualquer elemento):

  * {
      touch-action: manipulation;
  }

manipulação

Ative os gestos de panorâmica e de zoom, mas desative os gestos não padrão adicionais, como tocar duas vezes para ampliar.

Obrigado Ross, minha resposta se estende a dele: https://stackoverflow.com/a/53236027/9986657

Jan
fonte
1
Isso deve ser marcado como a resposta. Tentei colocá-lo apenas em html e body, mas não funcionou no iOS 13.2. Isso funciona.
R OMS
Isso não funciona no iOS 13 por si só, mas em conjunto com este código, ele bloqueia o toque para ampliar o aplicativo React completamente. document.getElementById('root').addEventListener('click', () => {})
Sergei
apple disabled toque para zoom no ios13, como você pode dizer que não funciona no iOS13?
oygen
15

Se você precisa de uma versão que funcione sem jQuery , modifiquei a resposta de Wouter Konecny (que também foi criada modificando esta essência por Johan Sundström ) para usar o 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();
}

Em seguida, adicione um manipulador de eventos touchstartque chama esta função:

myButton.addEventListener('touchstart', preventZoom); 
Evrim Persembe
fonte
3
brilhante. só queria mencionar que precisava adicionar um addEventListener para chamar isso. myButton.addEventListener('touchstart', preventZoom);
Martin Jakubik
11

Você deve definir a propriedade css touch-actionpara none, conforme descrito neste outra resposta https://stackoverflow.com/a/42288386/1128216

.disable-doubletap-to-zoom {
    touch-action: none;
}
Jonathan Morales Vélez
fonte
1
Isso funciona ... mas e se eu quiser desativar o zoom, mas deixar outros eventos de toque? Tenho uma mesa grande e isso também desativa a rolagem.
FrenkyB
2
Se você deseja apenas se livrar do zoom de toque duplo, defina o valor como 'touch-action: manipulate;' Isso ainda permitirá panorâmicas e zoom de pinça. Observação importante: isso também ajuda a se livrar do atraso do clique que os navegadores introduziram para implementar o zoom de toque duplo. consulte developer.mozilla.org/en-US/docs/Web/CSS/touch-action
cschuff
Em qual tag HTML essa classe deve ser adicionada?
Razvan Zamfir
Acho que você pode simplesmente adicioná-lo a qualquer elemento que não queira que use para aumentar o zoom. Por exemplo, no meu caso, não queria que o usuário ampliasse nenhuma parte da minha página, então adicionei à tag body.
Jonathan Morales Vélez
2
* {
    -ms-touch-action: manipulation;
    touch-action: manipulation;
}

Desative o toque duplo para aumentar o zoom em telas sensíveis ao toque. Internet explorer incluído.

Erçin Dedeoğlu
fonte
1

Simples evitar o comportamento padrão click, dblclickou touchendeventos irá desactivar a funcionalidade de zoom.

Se você já tiver um retorno de chamada em um desses eventos, basta chamar a event.preventDefault().

William Grasel
fonte
1
Isso funcionou para mim. Eu estava definindo meu próprio evento touchstart em um botão e queria desabilitar a função de zoom.
Rick Giuly
1

Se alguém como eu está enfrentando esse problema ao usar o Vue.js , basta adicionar .prevent para resolver o problema:@click.prevent="someAction"

Sølve Tornøe
fonte
0

Isso impedirá o zoom de toque duplo em elementos no 'corpo', que pode ser alterado para qualquer outro seletor

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

});

Mas isso também evitou que meu evento de clique fosse acionado quando clicado várias vezes, então eu tive que vincular outro evento para acionar os eventos em vários cliques

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

No touchstart, adicionei o código para evitar o zoom e acionar um clique.

$('.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
fonte
-1

Presumo que tenho uma <div>área de contêiner de entrada com texto, controles deslizantes e botões e desejo inibir toques duplos acidentais nela <div>. O seguinte não inibe o zoom na área de entrada e não se relaciona ao toque duplo e zoom fora da minha <div>área. Existem variações dependendo do aplicativo do navegador.

Eu apenas tentei.

(1) Para Safari no iOS e Chrome no Android, e é o método preferido. Funciona exceto para aplicativo de Internet na Samsung, onde desativa os toques duplos não totalmente <div>, mas pelo menos em elementos que controlam os toques. Ele retorna return false, com exceção de texte 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 aplicativo de Internet integrado no Android (5.1, Samsung), inibe toques duplos no <div>, mas inibe o zoom em <div>:

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

(3) Para o Chrome no Android 5.1, desativa o toque duplo, não inibe o zoom e não faz nada sobre o toque duplo nos outros navegadores. O duplo toque inibidor do <meta name="viewport" ...>é irritante, pois <meta name="viewport" ...>parece uma boa prática.

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

Aqui vamos nós

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

não tenho certeza
fonte