Javascript: любые способы обхода Chrome для Android, чтобы отключить touchmove и коснуться прослушивателей событий, кроме использования event.preventDefault()?

При использовании прослушивателей событий с событиями touchmove и touchhend я не могу заставить Chrome для Android распознавать те события, если я не впервые использовал event.preventDefault(); ранее в коде. Если я не хочу блокировать функциональность прокрутки по умолчанию, есть ли другой способ обхода, который я могу использовать, чтобы заставить Chrome для Android признать эти события?

Пример кода:

$(document).ready(function () {
// Bind touch event listeners.
var elem = $('html').get(0);
elem.addEventListener('touchstart', function (e) { console.info('"touchstart" detected. Coordinates - ' + getCoord(e)); });
elem.addEventListener('touchmove', function (e) { console.info('"touchmove" detected. Coordinates - ' + getCoord(e)); });
elem.addEventListener('touchend', function (e) { console.info('"touchend" detected. Coordinates - ' + getCoord(e)); });

function getCoord(e) {
var touch = false;
if (e.touches.length > 0) {
touch = e.touches[0];
} else {
touch = e.changedTouches[0];
}
if (touch) {
return 'x: ' + touch.pageX + ', y: ' + touch.pageY;
}
}

Пример скрипки здесь: http://jsfiddle.net/jQ2VS/1/

Ответ 1

Google Chrome будет запускать событие touchcancel около 200 миллисекунд после touchstart, если он считает, что пользователь выполняет панорамирование/прокрутку и вы не вызываете event.preventDefault().

Предполагая, что вы хотите перехватить события горизонтального касания и позволить событиям вертикального касания вызвать панорамирование/прокрутку, обходным путем было бы следующее:

  • В touchstart сохраните координаты в переменной и установите iteration в 0.
  • Для каждого события touchmove установите iteration в iteration +1.
  • Когда iteration равно 4 (просто "магическое число", которое, как мне показалось, было надежным в моей настройке), вычислите общие дельты смещения касания для осей x и y. EDIT: на мобильных устройствах вы получите только одно касание без события .preventDefault()
  • Если смещение по оси x > смещение оси y * 3, то пожар event.preventDefault(). (Это гарантирует, что жест в значительной степени горизонтальный).

Нижняя сторона этого заключается в том, что пользователь может либо прокручивать влево/вправо, либо прокручивать вверх/вниз.

Ответ 2

Наконец, я нашел решение (чисто js) даже в случае, если вы можете использовать его для прокрутки:

var swipe = function() {

    var touchX, touchY, movX, movY, go;

    function prevent(e){
        e.preventDefault();
    }

    function start(e) {
        go = false;
        document.addEventListener("touchmove", prevent, false);
        touchX = e.touches[0].pageX;
        touchY = e.touches[0].pageY;
    }

    function move(e) {
        movX = e.touches[0].pageX - touchX;
        movY = e.touches[0].pageY - touchY;
        if(!go) {
            (Math.abs(movY) < Math.abs(movX)) ? go = true : stop(e);
        } else {
            /* *************** */
            // cast your spell
            /* *************** */
        }
    }

    function stop(e) {
        document.removeEventListener("touchmove", prevent, false);
    }

    document.addEventListener("touchstart", start, true);
    document.addEventListener("touchmove", move, true);
    document.addEventListener("touchend", stop, true);
    document.addEventListener("touchleave", stop, true);
    document.addEventListener("touchcancel", stop, true);

}

Надеюсь на эту помощь.

Ответ 3

Самый простой ответ заключается в том, что вы должны предотвратитьDefault для первого события touchmove, иначе они будут отменены.

Ответ 4

Я обнаружил, что предотвращение работы touchcancel прекрасное.

Ответ 5

Принятый ответ неверен.

В Android, если preventDefault не установлен на touchstart, устройство предполагает собственную прокрутку, и больше никаких событий касания не отправляются в webview. Если параметр preventDefault установлен, вся естественная прокрутка отключена.

Существует прокладка для создания событий прокрутки с естественной прокруткой здесь: https://github.com/TNT-RoX/android-swipe-shim