2013-04-11 3 views
13

Ich versuche eine Webseite zu erstellen, die die Berührung des Benutzers erkennt und Objekte entlang der Zeichenfläche zieht und anzeigt.Android-Browser: touchcancel wird ausgelöst, obwohl touchmove preventDefault

So etwas wie dies ich tue:

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

Es bis irgendwann gut funktioniert.

Das Problem ist, dass, sobald ich zu viele objs laden, scheint es mir, dass die Berührungsbewegungs zu lange dauert, zu reagieren und touchcancel ausgelöst wird. Das Problem ist, dass, sobald touchcancel ausgelöst werden, ich nicht mehr touchmove s Ereignisse erhalte, und ich kann die Bewegung nicht mehr spüren.

Ist jemand mit diesem Problem konfrontiert? Ich kenne den Fehler in Android, wo Sie preventDefault (touchend event in ios webkit not firing?) anrufen müssen, aber in diesem Fall scheint es, dass es wegen der Speicherbelastung nicht funktioniert.

Vielen Dank!

+1

Ich habe das gleiche Problem auf Android 2.3. Android 4+ scheint in Ordnung zu sein. Haben Sie etwas zu diesem Thema gefunden? – dioslaska

+0

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

+0

Für die Zukunft, hier die Antwort funktioniert perfekt: http://stackoverflow.com/questions/10367854/html5-android-touchcancel –

Antwort

2

Dieses Problem kann auf einen Fehler (Funktion?) In Chrome/Android zurückzuführen sein. Siehe this bug report.

Dieser Test zeigt das Verhalten (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> 

ich nicht die touchcancel Veranstaltung zufällig abgefeuert werden. Stattdessen wird es ausgelöst, wenn ~ 200 ms benötigt werden, um von einem touchmove Event-Handler zurückzukehren.

+0

ich durch Bindung touchcancel lösen touchEnd –

+7

bitte erklären, "Ich löse durch bindenden touchcancel touchend" – FlavorScape

3

wie diese

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

    }) 
} 

Verwendung SetTimeout wickeln Sie Logik in Berührungsbewegungs zu nehmen, kann dieses Problem lösen

0

Touchcancel speziell die Kontrolle über Touch-Ereignisse ist so konzipiert und regelmäßigen Browser Aktionen wie Schwenk- oder Zoom durchführen, nachdem eine sehr kleine Berührung und Bewegung (fast 20px, abhängig vom Browser).

Ihre einzigen Optionen sind entweder:

  1. Switch to Pointer Events und verwenden Sie die touch-action CSS-Eigenschaft as explained here zu pointercancel von Brennen verhindern (empfohlen, aber erfordert Android 5+)
  2. event.preventDefault() innen hinzufügen Ihr touchmove Event-Handler, aber dies wird auch alle Standard-Aktionen wie Bildlauf, Schwenken, Zoom, etc.
deaktivieren

Sie können nicht versuchen zu stornieren oder preventDefault() innerhalb einer touchcancel Funktion, weil es dafür zu spät sein wird; Der Browser hat bereits aufgehört, das Ereignis touchmove zu hören. Dies ist mit Absicht kein Bug.