2016-01-20 24 views
14

Sto utilizzando FastClick su una pagina con collegamenti di grandi dimensioni perché voglio ignorare il ritardo di 300 ms per i tocchi nei browser mobili. Ho uno stile "highlight" per gli stati dei link ':active e sta sparando correttamente velocemente, grazie a FastClick.C'è un modo per impedire a fastclick di attivare lo stato "attivo" sullo scorrimento?

Il mio problema è che - almeno in Safari Safari - si attiva anche mentre si tocca e si scorre per scorrere la pagina. Questo fa sembrare che non puoi scorrere la pagina senza che tu stia pensando di provare a toccare i link.

C'è un modo per impedirgli di sparare quando qualcuno scorre?

risposta

2

Forse è possibile aggiungere la classe needsclick al corpo?

<body class="needsclick"> 

... 

</body> 

Solo un'idea :)

+0

Grazie ... che sarebbe effettivamente impedire FastClick di lavorare per i controlli a tutti. –

2

Nizza domanda! +1

Questo problema non ha nulla a che fare con FastClick, ma FastClick rende la soluzione al tuo problema più complessa. Quindi mi limiterò a puro JavaScript e Raw Touch Events)

Su un dispositivo mobile touch l'implementazione della webview è significativamente diversa dal browser web desktop per ragioni specifiche della piattaforma. Una funzione importante in questo caso è lo scorrimento del momento nella visualizzazione Web. Lo scorrimento del momento è una funzione hardware accelerata del dispositivo. Quindi, quando un'area sensibile viene toccata sullo schermo, l'hardware identifica il tocco e allega un timer per il conto alla rovescia di 200 millisecondi all'area scorrevole, che, una volta attivato, inserisce l'area in una scroll accelerata hardware. Quando l'hardware è nello stato, non trasmette eventi touch perché sono specifici per lo scorrimento accelerato hardware. Il timer può essere annullato e lo scorrimento del momento evitato utilizzando preventDefault sull'evento di tocco entro 200 millisecondi previsti.

Ecco come approccio a questo problema. Presumo che tu stia usando la scroll nativa i.e overflow:scroll. Il metodo consiste nel collegare un evento touchstart all'elemento che si desidera toccare. Dopo l'attivazione dell'evento touchstart, il gestore eventi allega gli eventi touchend, e touchcancel all'elemento di destinazione. Viene avviato un timer setTimout che rimuove gli eventi appena aggiunti dopo 140 ms.

Ecco alcune clip per il mio codice di produzione: ho due metodi di eventi per l'aggiunta e la rimozione di eventi da collezioni:

var eventify = (function() { 
    function eventify(type, el, callback, phase) { 
     phase = phase || false; 
     if ((el.constructor.toString().contains('NodeList')) || (el.constructor.toString().contains('HTMLCollection'))) { 
      [].forEach.call(el, function (element) { 
       if (!element.hasEvent(type)) { 
        element.addEvent(type); 
        HTMLElement.prototype.addEventListener.apply(element, [type, callback, phase]); 
       } 
      }); 
     } else { 
      if (!el.hasEvent(type)) { 
       el.addEvent(type); 
       HTMLElement.prototype.addEventListener.apply(el, [type, callback, phase]); 
      } 
     } 
     return callback; 
    } 

    return eventify 
})(); 

var uneventify = (function() { 
    function uneventify(type, el, callback) { 
     if ((el.constructor.toString().contains('NodeList')) || (el.constructor.toString().contains('HTMLCollection'))) { 
      [].forEach.call(el, function (element) { 
       if (element.hasEvent(type)) { 
        element.removeEvent(type); 
        HTMLElement.prototype.removeEventListener.apply(element, [type, callback]); 
       } 
      }); 
     } else { 
      if (el.hasEvent(type)) { 
       el.removeEvent(type); 
       HTMLElement.prototype.removeEventListener.apply(el, [type, callback]); 
      } 
     } 
    } 

    return uneventify 
})(); 

Poi Ho un metodo tapify per gli eventi rubinetto sul scroller:

var tapify = (function() { 
    function tapify(el, callback) { 
     eventify('touchstart', el, function (e) { 
      var that = this; 
      var start = e.pageY; 
      var target = e.target; 
      function dynamicEvents() { 
       var endfn = eventify('touchend', target, function (evt) { 
        e.preventDefault(); 
        e.stopImmediatePropagation(); 
        evt.preventDefault(); 
        evt.stopImmediatePropagation(); 
        uneventify('touchmove', target, movefn); 
        uneventify('touchend', target, endfn); 
        uneventify('touchcancel', target, cancelfn); 
        callback && callback(target); 
       }); 
       var cancelfn = eventify('touchcancel', target, function (evt) { 
        e.preventDefault(); 
        e.stopImmediatePropagation(); 
        evt.preventDefault(); 
        evt.stopImmediatePropagation(); 
        uneventify('touchmove', target, movefn); 
        uneventify('touchend', target, endfn); 
        uneventify('touchcancel', target, cancelfn); 
        callback && callback(target); 
       }); 
       var movefn = eventify('touchmove', target, function (evt) { 
        var distance = start - evt.pageY; 
        if (distance > 20) { 
         uneventify('touchend', target, endfn); 
         uneventify('touchcancel', target, cancelfn); 
         uneventify('touchmove', el, movefn); 
        } 
       }); 
       setTimeout(function() { 
        uneventify('touchmove', target, movefn); 
        uneventify('touchend', target, endfn); 
        uneventify('touchcancel', target, cancelfn); 
       }, 140); 
      } 
      if (global.isIos) setTimeout(function() { 
       dynamicEvents(); 
      }, 60); 
      else dynamicEvents(); 
     }, false); 
    } 
    return tapify; 
})(); 

Uso global.isIos per identificare il dispositivo di destinazione. Android interrompe l'invio di eventi di tocco a webview fino a 200ms.

Poi per fissare l'evento a un elemento o un insieme di elementi, utilizzare:

tapify(document.querySelectorAll('button'), function (e) { 
     //your event handler here!! 
}); 

Spero che questo aiuti

+0

È possibile utilizzare questo stesso metodo per scorrere e trascinare gli eventi su una superficie di scorrimento nativa. –

+0

Grazie per la risposta! In questo momento speravo di provare qualcosa di compatibile con FastClick e ... come un principiante JS sono certamente sopra la mia testa con la tua risposta, ma non vedo come si connette con FastClick. Ma se divento coraggioso cercherò di aggiungere parte del tuo codice al mio progetto. –

+0

suggerisco di collegare FastClick solo agli elementi che lo richiedono e non al documento. –