Подтвердить что ты не робот

Андроид: touchcancel уволен, хотя touchmove имеет предупреждениеDefault

Я пытаюсь создать веб-страницу, которая ощущает прикосновение пользователя и тащит и объект вдоль холста.

Итак, я делаю что-то вроде этого:

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

Он работает нормально до некоторой точки.

Проблема в том, что, как только я загружаю слишком много объектов, мне кажется, что touchmove слишком долго реагирует, и срабатывает touchcancel. Проблема в том, что, как только срабатывает touchcancel, я больше не получаю touchmove, и я больше не могу ощущать движение.

Кто-нибудь сталкивался с этой проблемой? Я знаю об ошибке в Android, где вы должны называть preventDefault (touchhend событие в ios webkit, а не стрелять?), но в этом случае кажется, что он не работает из-за нагрузки на память.

Спасибо!

4b9b3361

Ответ 1

как это

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

    })
}

использовать setTimeout, чтобы обернуть вас логикой в ​​touchmove, может решить эту проблему.

Ответ 2

Эта проблема может быть вызвана ошибкой (функцией?) в Chrome/Android. См. этот отчет об ошибках.

Этот тест демонстрирует поведение (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>

Я не вижу случай, когда событие touchcancel запускается случайным образом. Вместо этого он запускается всякий раз, когда требуется 200 мс для возврата из обработчика события touchmove.

Ответ 3

Touchcancel специально предназначен для управления событиями касания и выполнения обычных действий браузера, таких как панорамирование или масштабирование после очень небольшого касания и действие перемещения (почти 20px, в зависимости от браузера).

Возможны только следующие варианты:

  • Переключитесь на События указателя и используйте свойство touch-action CSS как объясняется здесь предотвратить pointercancel от стрельбы (рекомендуется, но требуется Android 5 +)
  • Добавьте event.preventDefault() внутри обработчика событий touchmove, но это также отключит любые действия по умолчанию, такие как прокрутка, панорамирование, масштабирование и т.д.

Вы не можете выполнить отмену или preventDefault() внутри функции touchcancel, потому что для этого будет слишком поздно; браузер уже перестает слушать событие touchmove. Это по дизайну, а не ошибка.