Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android browser: touchcancel being fired althought touchmove has preventDefault

I'm trying to build a Webpage that senses the touch from the user and drags and object along the canvas.

So I'm doing something like this:

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

It works fine until some point.

The problem is that as soon as I load too many objs, it seems to me that the touchmove takes too long to respond, and touchcancel gets triggered. The problem is that as soon as touchcancel get triggered I don't receive any more touchmoves events, and I cannot sense the movement anymore.

Did anyone face this problem? I know about the bug in Android where you must call preventDefault (touchend event in ios webkit not firing?) but on this case it seems that it is not working because of the memory burden.

Thank you!

like image 963
José Leal Avatar asked Apr 11 '13 08:04

José Leal


2 Answers

like this

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

    })
}

use setTimeout to wrap you logic in touchmove can solve this problem

like image 56
tenny lv Avatar answered Sep 28 '22 11:09

tenny lv


This problem may be due to a bug (feature?) in Chrome/Android. See this bug report.

This test demonstrates the behavior (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>

I don't find the touchcancel event to be fired randomly. Instead, it is fired whenever it takes ~200 ms to return from a touchmove event handler.

like image 38
Rich Apodaca Avatar answered Sep 28 '22 11:09

Rich Apodaca