Прикоснитесь к движению, застрявшему. Игнорируйте попытку отменить сенсорную кнопку

Я возился с событиями касания на сенсорном слайдере, и я продолжаю получать следующую ошибку:

Игнорированная попытка отменить событие touchmove с cancelable = false, например, поскольку выполняется прокрутка и не может быть прерываться.

Я не уверен, что вызывает эту проблему, я новичок в работе с событиями касания и не могу решить эту проблему.

Вот код, обрабатывающий событие касания:

Slider.prototype.isSwipe = function(threshold) {
    return Math.abs(deltaX) > Math.max(threshold, Math.abs(deltaY));
}


Slider.prototype.touchStart = function(e) {

    if (this._isSliding) return false;

      touchMoving = true;
      deltaX = deltaY = 0;

    if (e.originalEvent.touches.length === 1) {

        startX = e.originalEvent.touches[0].pageX;
        startY = e.originalEvent.touches[0].pageY;

        this._$slider.on('touchmove touchcancel', this.touchMove.bind(this)).one('touchend', this.touchEnd.bind(this));

        isFlick = true;

        window.setTimeout(function() {
            isFlick = false;
        }, flickTimeout);
    }
}


Slider.prototype.touchMove = function(e) {

    deltaX = startX - e.originalEvent.touches[0].pageX;
    deltaY = startY - e.originalEvent.touches[0].pageY;

    if(this.isSwipe(swipeThreshold)) {
        e.preventDefault();
        e.stopPropagation();
        swiping = true;
    }
    if(swiping) {
        this.slide(deltaX / this._sliderWidth, true)
    }
}


Slider.prototype.touchEnd = function(e) {

    var threshold = isFlick ? swipeThreshold : this._sliderWidth / 2;

    if (this.isSwipe(threshold)) {
        deltaX < 0 ? this.prev() : this.next();
    }
    else {
        this.slide(0, !deltaX);
    }

    swiping = false;

    this._$slider.off('touchmove', this.touchMove).one(transitionend, $.proxy(function() {
        this.slide(0, true);
        touchMoving = false;
    }, this));
}

Вы можете найти фактический слайдер здесь, на этом пером.

Если вы проскользните достаточно быстро, это вызовет ошибку и иногда застрянет посреди салфетки. Все еще не могу окутать голову, почему она не работает. Любая помощь/понимание будут оценены. Не уверен, что я делаю неправильно.

Ответы

Ответ 1

Событие должно быть cancelable. Добавление оператора if решает эту проблему.

if (e.cancelable) {
   e.preventDefault();
}

В вашем коде вы должны поместить его здесь:

if (this.isSwipe(swipeThreshold) && e.cancelable) {
   e.preventDefault();
   e.stopPropagation();
   swiping = true;
}

Ответ 2

У меня была эта проблема, и все, что мне нужно было сделать, это return true от touchhend, и предупреждение ушло.

Ответ 3

Вызов preventDefault на touchmove, пока вы активно прокручиваете, не работает в Chrome. Чтобы предотвратить проблемы с производительностью, вы не можете прервать прокрутку.

Попробуйте вызвать preventDefault() из touchstart, и все должно быть в порядке.

Ответ 4

Пожалуйста, удалите e.preventDefault(), потому что event.cancelable от touchmove имеет значение false. Таким образом, вы не можете вызвать этот метод.

Ответ 5

Я знаю, что это старый пост, но у меня было много проблем, пытающихся решить эту проблему, и я наконец сделал это, поэтому я хотел поделиться.

Моя проблема заключалась в том, что я добавлял прослушиватель событий в ontouchstart и удалял его в функциях ontouchend - что-то вроде этого

function onTouchStart() {
  window.addEventListener("touchmove", handleTouchMove, {
    passive: false
  });
}

function onTouchEnd() {
  window.removeEventListener("touchmove", handleTouchMove, {
    passive: true
  });
}

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

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

let stopScrolling = false;

window.addEventListener("touchmove", handleTouchMove, {
  passive: false
});

function handleTouchMove(e) {
  if (!stopScrolling) {
    return;
  }
  e.preventDefault();
}

function onTouchStart() {
  stopScrolling = true;
}

function onTouchEnd() {
  stopScrolling = false;
}

На самом деле я использовал React, поэтому мое решение включало установку состояния, но я упростил его для более общего решения. Надеюсь, это кому-нибудь поможет!