Javascript 触摸移动卡住 忽略尝试取消触摸移动

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/26478267/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-22 22:56:49  来源:igfitidea点击:

Touch move getting stuck Ignored attempt to cancel a touchmove

javascriptjqueryevent-handlingslidertouch

提问by souporserious

I'm messing around with touch events on a touch slider and I keep getting the following error:

我正在处理触摸滑块上的触摸事件,并且不断收到以下错误:

Ignored attempt to cancel a touchmove event with cancelable=false, for example because scrolling is in progress and cannot be interrupted.

忽略尝试取消带有 cancelable=false 的 touchmove 事件,例如因为滚动正在进行且不能被中断。

I'm not sure what is causing this problem, I am new to working with touch events and can't seem to fix this problem.

我不确定是什么导致了这个问题,我是接触事件的新手,似乎无法解决这个问题。

Here is the code handling the touch event:

这是处理触摸事件的代码:

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

You can find the actual slider here at this pen.

你可以在这支笔上找到实际的滑块。

If you swipe through fast enough it will throw the error and sometimes get stuck in the middle of a swipe. Still can't wrap my head around why it is not working. Any help/insight would be greatly appreciated. Not sure what I am doing wrong.

如果你的滑动速度足够快,它会抛出错误,有时会卡在滑动的中间。仍然无法理解为什么它不起作用。任何帮助/见解将不胜感激。不知道我做错了什么。

采纳答案by SrAxi

The event must be cancelable. Adding an ifstatement solves this issue.

事件必须是cancelable。添加if语句可以解决此问题。

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

In your code you should put it here:

在你的代码中,你应该把它放在这里:

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

回答by Chet

I had this problem and all I had to do is return truefrom touchend and the warning went away.

我遇到了这个问题,我所要做的就是return true从 touchend 开始,警告就消失了。

回答by Jeff Hernandez

I know this is an old post but I had a lot of issues trying to solve this and I finally did so I wanted to share.

我知道这是一篇旧帖子,但我在尝试解决这个问题时遇到了很多问题,我终于做到了,所以我想分享。

My issue was that I was adding an event listener within the ontouchstart and removing it in the ontouchend functions - something like this

我的问题是我在 ontouchstart 中添加了一个事件侦听器并在 ontouchend 函数中将其删除 - 像这样

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

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

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

For some reason adding it removing it like this was causing this issue of the event randomly not being cancelable. So to solve this I kept the listener active and toggled a boolean on whether or not it should prevent the event - something like this:

出于某种原因,像这样添加它删除它会导致此事件随机无法取消的问题。所以为了解决这个问题,我保持监听器处于活动状态并切换一个布尔值是否应该阻止事件 - 像这样:

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

I was actually using React so my solution involved setting state, but I've simplified it for a more generic solution. Hopefully this helps someone!

我实际上使用的是 React,所以我的解决方案涉及设置状态,但我已将其简化为更通用的解决方案。希望这对某人有所帮助!

回答by MartinMoizard

Calling preventDefaulton touchmovewhile you're actively scrolling is not working in Chrome. To prevent performance issues, you cannot interrupt a scroll.

preventDefaulttouchmove您主动滚动时调用在 Chrome 中不起作用。为防止出现性能问题,您不能中断滚动。

Try to call preventDefault()from touchstartand everything should be ok.

尝试调用preventDefault()touchstart,一切都应该没问题。

回答by mqliutie

Please remove e.preventDefault(), because event.cancelableof touchmove is false. So you can't call this method.

请删除e.preventDefault(),因为event.cancelabletouchmove 是false。所以你不能调用这个方法。