2010-06-23 23 views
11

Sto creando un sito su Safari per iPad. Ho bisogno di evitare che lo zoom evento toccando due volte ma ho due problemi:Safari iPad: impedisce lo zoom sul doppio tocco

  • un doppio tap non genera alcun evento, quindi non posso usare "event.preventDefault();"
  • Ho bisogno di farlo solo quando alcune condizioni sono soddisfatte, quindi non posso usare il tag "<meta name = "viewport" content = "user-scalable = no">" ... Se l'ho fatto, gli utenti non potrebbero mai zoomare sulla mia pagina.

Come posso risolvere questi problemi?

risposta

7

Mobile Safari non supporta l'evento ondblclick javascript. È interpretato da Safari come "zoom".

Raul Sanchez ha pubblicato una possibile soluzione: http://appcropolis.com/implementing-doubletap-on-iphones-and-ipads/

+2

Ho usato questa soluzione davvero ... Questo argomento è davvero dettagliato, grazie! Per i visitatori, l'idea principale è la seguente: in primo luogo, prendere un evento "tap". Quindi, se viene lanciato un altro evento "tap" prima di 500 ms: è un "doppio tocco", quindi se puoi interrompere l'evento qui -> no "tocca due volte" :) Vedi il link per ulteriori spiegazioni. – Nicolas

7

Qui sta un plugin jQuery che ho scritto per lo stesso scopo - disattivando selettivamente doppio tocco zoom su determinati elementi della pagina (nel mio caso, pulsanti di navigazione per capovolgere le pagine) Voglio rispondere ad ogni tocco (incluso il doppio tocco) come un normale evento click, senza iOS "touch magic".

Per utilizzarlo, è sufficiente eseguire qualcosa come $('.prev,.next').nodoubletapzoom(); sugli elementi a cui tieni. (Edit: ora ignora anche pizzichi)

// jQuery no-double-tap-zoom plugin 

// Triple-licensed: Public Domain, MIT and WTFPL license - share and enjoy! 

(function($) { 
    var IS_IOS = /iphone|ipad/i.test(navigator.userAgent); 
    $.fn.nodoubletapzoom = function() { 
    if (IS_IOS) 
     $(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); 
+0

Funziona, ma ha un bug: more-than-two-tap. Aggiungi questo dopo aver attivato i clic in su inghiottito: '$ (questo) .data ('lastTouch', 0);'. Senza di esso si ottengono quattro clic quando si tocca tre volte (possibile altro sul quadruplo-tap). Con esso si ottengono tre clic su triplo tocco, quattro clic su quadruplo-tap. L'idea è che potresti avere un elemento che dovrebbe rispondere a molti tocchi consecutivi (anziché essere trattenuto, per qualsiasi motivo). –

+0

Questa soluzione sembra impedire tutti i clic ripetuti, se il ritardo tra di essi è inferiore a 500 ms. Sarebbe in qualche modo possibile consentire di fare clic per es. 5 volte in un lasso di tempo di 500 ms E ancora impedire lo zoom? Avrei bisogno di un modo in cui i clic ripetuti funzionano nei dispositivi del mouse. –

+0

Ho trovato una soluzione semplice al mio problema di sparatutto: http://stackoverflow.com/a/30744654/1691517. Non "aspetta" 500 ms fino a quando non consente un nuovo clic, ma lo fa immediatamente, ma impedisce comunque il tap-zooming indesiderato. –

1

solo seting finestra può non essere sempre sufficiente - in alcuni casi potrebbe essere necessario chiamare anche event.preventDefault(); sul gestore del touchstart.

5

Ho modificato la soluzione javascript di @ ecmanaut per fare due cose.

  1. Uso modernizr, quindi inserirà una classe ct. Touch nel nodo html, in modo da poter rilevare gli schermi tattili invece di utilizzare il rilevamento degli agenti utente. Forse c'è un approccio "senza modernizzazione", ma io non lo so.
  2. Separo ogni "clic" in modo che avvengano separatamente, se si fa clic una volta, verrà fatto clic una volta, se si fa rapidamente clic sul pulsante/trigger, verrà conteggiato più volte.
  3. alcune modifiche minori di formattazione del codice, preferisco ogni var definita separatamente ecc., Questa è più una cosa "me" di ogni altra cosa, suppongo che potresti semplicemente ripristinare ciò, non accadrà nulla di brutto.

Credo che queste modifiche rendono meglio, causa si può incrementare un contatore 1,2,3,4 invece di 2,4,6,8

Ecco il codice modificato:

// jQuery no-double-tap-zoom plugin 
// Triple-licensed: Public Domain, MIT and WTFPL license - share and enjoy! 
// 
// [email protected]: I modified this to 
// use modernizr and the html.touch detection and also to stop counting two 
// clicks at once, but count each click separately. 

(function($) { 
    $.fn.nodoubletapzoom = function() { 
     if($("html.touch").length == 0) return; 

     $(this).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 
      $(this).trigger('click'); 
     }); 
    }; 
})(jQuery); 

il applicare la nodoubletapzoom() per il tag body, come questo

$("body").nodoubletapzoom(); 

la costruzione html, dovrebbe essere qualcosa di simile

<body> 
    <div class="content">...your content and everything in your page</div> 
</body> 

Poi, nel tuo javascript, si legano i gestori di clic come questo

$(".content") 
    .on(".mydomelement","click",function(){...}) 
    .on("button","click",function(){...}) 
    .on("input","keyup blur",function(){...}); 
    // etc etc etc, add ALL your handlers in this way 

è possibile utilizzare qualsiasi gestore di eventi jQuery e qualsiasi nodo dom. ora non devi fare altro, devi collegare tutti i gestori di eventi in questo modo, non ho provato in un altro modo, ma in questo modo funziona assolutamente solido, puoi letteralmente rapare lo schermo 10 volte al secondo e non ingrandisce e registra i clic (ovviamente non 10 al secondo, l'ipad non è così veloce, ciò che intendo è, non è possibile attivare lo zoom)

Penso che questo funzioni perché si allega il nozoom gestire il corpo e quindi collegare tutti i gestori di eventi al nodo ".content", ma delegando al nodo specifico in questione, quindi jquery cattura tutti i gestori nell'ultima fase prima che l'evento scoppiasse sul tag del corpo.

il vantaggio principale di questa soluzione è che devi assegnare il gestore nodoubletapzoom() al corpo, lo fai solo una volta, non una volta per ogni elemento, quindi è molto meno lavoro, sforzo e pensiero necessari per fare le cose.

questo ha l'ulteriore vantaggio in quanto se si aggiunge contenuto utilizzando AJAX, hanno automaticamente i gestori pronti e in attesa, suppongo che se lo desideri DIDNT, allora questo metodo non funzionerà per te e dovrai regolalo di più.

Ho verificato che questo codice funzioni su ipad, è davvero bello, ben fatto a @ecmanaut per la soluzione primaria !!

** Modificato il Sabato 26 maggio, perché ho trovato quello che sembra essere una soluzione perfetta con assolutamente il minimo sforzo

0

La risposta accettata 'doppio click' è per me un po 'gonfio' e l'utilizzo di un timestamp .. ... perché? Guarda questa semplice implementazione senza eccessivo 'gonfiarsi'.

function simulateDblClickTouchEvent(oo) 
{ 
var $oo = !oo?{}:$(oo); 
if(!$oo[0]) 
    { return false; } 

$oo.bind('touchend', function(e) 
{ 
    var ot = this, 
    ev = e.originalEvent; 

    if(ev && typeof ev.touches == 'object' && ev.touches.length > 1) 
    { return; } 

    ot.__taps = (!ot.__taps)?1:++ot.__taps; 

    if(!ot.__tabstm) // don't start it twice 
    { 
    ot.__tabstm = setTimeout(function() 
    { 
     if(ot.__taps >= 2) 
     { ot.__taps = 0; 
      $(ot).trigger('dblclick'); 
     } 
     ot.__tabstm = 0; 
     ot.__taps = 0; 
    },800); 
    } 
}); 
return true; 
}; 

Usage:

simulateDblClickTouchEvent($('#example')); 

or 

simulateDblClickTouchEvent($('.example')); 

funzione restituisce vero o falso quando l'evento viene rilegato o meno.

Per evitare le cose di zoom e scorrere fare questo:

function disableTouchScroll() 
{ 

try { 
    document.addEventListener('touchmove', function(e) { e.preventDefault(); }, true); 
    $j('body')[0].addEventListener('touchmove', function(e) { e.preventDefault(); }, true); 
    } 
    catch(ee) { return false; } 
    return true; 
} 

anche con i CSS è facile da evitare zoom:

body * { -webkit-user-select:none; } 
  • = non efficiente, ma provare, funziona benissimo.

Cheers!

6

provare questo codice modificato. Dovrebbe funzionare per entrambi i dispositivi Android e iOS

(function($) { 
$.fn.nodoubletapzoom = function() { 
    $(this).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'); 
    }); 
}; 
})(jQuery); 

Applicare quindi il nodoubletapzoom() per il tag body

$("body").nodoubletapzoom(); 
+0

Grazie per questo! Ho fatto un esempio: http://jsbin.com/dihoxedika/1/. Il problema nel codice di ecmanauts era '$ (this) .trigger ('click'). Trigger ('click')'. Quando ho sostituito 'this' con' e.target' e rimosso il secondo trigger, ha iniziato a funzionare su Android Chrome. Il problema era che non erano possibili rapidi clic ripetuti. –

+0

si prega di accettare la risposta se è pertinente – Inventillect

2

Tutte le soluzioni che ho visto (in questa pagina e anche altrove) avere un lato effetto che impediscono nei clic ripetuti a velocità elevata. Consente un clic per 500 ms o simili. Questo può andar bene in alcuni casi, ma non per es. se si dispone di un tiratore o di pulsanti freccia per consentire il rapido spostamento da un articolo all'altro.

La soluzione più semplice è questa:

$('#nozoom').on('touchstart', function(e) 
{ 
    fn_start(e); 
    e.preventDefault(); 
}); 

Ciò richiede fn_start() (la funzione di callback reale) ogni volta che si avvia il tatto, ma impedisce poi di default zoomings ecc

L'esempio comparativo di lavoro è qui : http://jsbin.com/meluyevisi/1/. La casella verde impedisce, la casella rossa lo consente.

Problemi correlati