2013-04-11 9 views
13

Sto provando a creare una pagina Web che rileva il tocco dell'utente e trascina e obietta lungo la tela.Browser Android: touchcancel viene attivato anche se touchmove ha impedito Default

così sto facendo qualcosa di simile:

var touchStart = function(e) { 
    e.preventDefault(); 
    // Do stuff 
} 
var touchMove = function(e) { 
    e.preventDefault(); 
    console.log("Touch move"); 
    // Move objs 
} 
var touchEnd = function(e) { 
    e.preventDefault(); 
    console.log("Touch start!"); 
    // clean up stuff 
} 
var touchCancel = function(e) { 
    e.preventDefault(); 

    // Oh NO touch cancel! 
    console.log("Touch cancel!"); 

} 
bindElemOrig.addEventListener('touchstart', touchStart, false); 
bindElemOrig.addEventListener('touchmove', touchStart, false); 
bindElemOrig.addEventListener('touchend', touchStart, false); 
bindElemOrig.addEventListener('touchcancel', touchStart, false); 

E funziona bene fino a un certo punto.

Il problema è che, non appena si carica troppi objs, mi sembra che la touchmove impiega troppo tempo per rispondere, e touchcancel viene attivato. Il problema è che non appena viene attivato lo touchcancel non ricevo più altri touchmove s, e non riesco più a percepire il movimento.

Qualcuno ha affrontato questo problema? Conosco il bug in Android in cui è necessario chiamare preventDefault (touchend event in ios webkit not firing?) ma in questo caso sembra che non funzioni a causa del carico di memoria.

Grazie!

+1

Sto riscontrando lo stesso problema su Android 2.3. Android 4+ sembra essere ok. Hai trovato qualcosa su questo argomento? – dioslaska

+0

@dioslaska shim @ https: // github.com/TNT-RoX/android-swipe-shim –

+0

Per riferimento futuro, la risposta qui funziona perfettamente: http://stackoverflow.com/questions/10367854/html5-android-touchcancel –

risposta

2

Questo problema potrebbe essere dovuto a un bug (funzionalità?) In Chrome/Android. Vedi this bug report.

Questo test dimostra il comportamento (JSFiddle):

<!DOCTYPE html> 
<html> 
    <head> 
    <title></title> 
    <script> 
     var delay = 200; 

     var haltEvent = function(event) { 
     event.preventDefault(); 
     event.stopPropagation(); 
     }; 

     var pause = function() { 
     var startTime = new Date().getTime(); 

     while (new Date().getTime() < startTime + delay); 
     }; 

     window.addEventListener('load', function() { 
     var target = document.querySelector('#target'); 
     var status = document.querySelector('#status'); 

     target.addEventListener('touchstart', function(event) { 
      haltEvent(event); 
      status.innerHTML = '[touchstart]'; 
     }, true); 

     target.addEventListener('touchmove', function(event) { 
      pause(); 
      haltEvent(event); 
      status.innerHTML = '[touchmove]'; 
     }, true); 

     target.addEventListener('touchend', function(event) { 
      status.innerHTML = '[touchend]'; 
     }, true); 

     target.addEventListener('touchcancel', function(event) { 
      status.innerHTML = '[touchcancel]'; 
     }, true); 
     }); 
    </script> 
    <style> 
     #target { 
     background-color: green; 
     height: 300px; 
     } 

     #status { 
     text-align: center; 
     } 
    </style> 
    </head> 
    <body> 
    <div id="target"></div> 
    <p id="status">[]</p> 
    </body> 
</html> 

non trovo l'evento touchcancel per essere licenziato in modo casuale. Invece, viene attivato ogni volta che ci vogliono ~ 200 ms per tornare da un gestore di eventi touchmove.

+0

Io risolvo rilegando touchcancel al touchend –

+7

per favore spiega "Risolvo rilegando touchcancel al touchend" – FlavorScape

3

come questo

var touchMove = function(e) { 
    e.preventDefault(); 
    setTimeout(function(){ 
     console.log("Touch move"); 
    // Move objs 

    }) 
} 

uso setTimeout per avvolgervi logica touchmove può risolvere questo problema

0

Touchcancel è specificamente progettato per prendere il controllo di eventi di tocco e di eseguire azioni normali browser come pan e zoom dopo un tocco molto piccolo e azione di movimento (quasi 20px, a seconda del browser).

Le uniche opzioni sono per entrambi:

  1. Passare al Pointer Eventi e utilizzare la proprietà CSS touch-actionas explained here a impedire pointercancel da sparare (consigliato ma richiede Android 5+)
  2. Aggiungi event.preventDefault() all'interno il tuo gestore di eventi touchmove, ma disabiliterà anche azioni predefinite come scorrimento, panoramica, zoom, ecc.

Non è possibile tentare di annullare o preventDefault() all'interno di una funzione touchcancel perché sarà troppo tardi per quello; il browser ha già smesso di ascoltare l'evento touchmove. Questo è di progettazione, non un bug.

Problemi correlati