防止在JavaScript中主要在水平触摸手势上进行垂直移动滚动

时间:2018-08-17 02:39:25

标签: javascript jquery

我有一些JavaScript来处理网页上的触摸事件,并观察主要是水平的手势。当用户开始水平滑动时,我希望他们的手势效果开始,但是当他们垂直滑动时,页面应该自然滚动,否则会滚动。

尽管水平手势现在确实可以达到预期的效果,但是即使大多数动作是水平的,它们也似乎仍会引起垂直滚动,使触摸的上下移动量达到一定程度。在主要水平滑动时,如何解决此问题以防止垂直滚动?我使用preventDefault()stopPropagation()都没有效果。我想我确实确实缺少某些东西,但是我似乎找不到。

我已经尽力搜索相似的问题,但是我的搜索查询尚未返回anything that works

注意:我不想完全停止垂直滚动,即使笔势发生X值更改,如果Y更改较大,页面仍应滚动。我只希望垂直滚动在X更改大于Y更改时锁定(这是我的代码现在应该执行的操作)。

更新:我没想到从移动设备上检索控制台日志。在@ tushar-shukla的建议下,我检查了一下,发现以下错误:

[Intervention] Unable to preventDefault inside passive event listener due to target being treated as passive. See <URL>

这是我的代码(和a JSFiddle, if that's more your cup of tea)的精简版本:

var startX = undefined;
var startY = undefined;

function touchmove(ev) {
    var e = ev.originalEvent;

    // Set the initial start position if not already. Could also be done on touchstart
    if (startX===undefined) { startX=e.touches[0].pageX; }
    if (startY===undefined) { startY=e.touches[0].pageY; }

    // Calculate the change or displacement from the start.
    changeX = e.touches[0].pageX-startX;
    changeY = e.touches[0].pageY-startY;

    // If the change horizontally is greater than the change vertically...
    if (Math.abs(changeX)>Math.abs(changeY)) {

        // Do something with the gesture

        // Prevent vertical scrolling; Apparently this isn't doing it:
        ev.preventDefault();
        ev.stopPropagation();
        e.preventDefault();
        e.stopPropagation();

    }
}

$(document).on("touchmove",touchmove);

2 个答案:

答案 0 :(得分:0)

如果我理解正确,那么当用户水平滚动(或尝试)滚动时,您需要停止“垂直滚动”(这是意外的)。

我还没有测试过,但是也许可以用。

var startX;
$(document).on('touchstart', function(e) {
  startX = e.originalEvent.touches[0].clientX;
});

$(document).on('touchmove', function(e) {
  var endX = e.originalEvent.changedTouches[0].clientX;
  if (startX !== endX) {
    console.log('attempting horizontal scroll');
    e.preventDefault();
  }
});

答案 1 :(得分:0)

将移动设备连接到Chrome后,我检索了控制台日志,其中包含以下重复错误:

[Intervention] Unable to preventDefault inside passive event listener due to target being treated as passive. See <URL>

这是我解决问题所需的线索。现代移动浏览器具有passive and active event listeners,其中主动浏览器可以阻止事件的默认操作,而被动浏览器则不能。这是针对触摸手势之类的性能优化,即使在体积较大的网页上也需要尽可能平稳地运行。

JavaScript自动将被动事件侦听器用于诸如touchmove之类的事件。尽管JavaScript在附加事件监听器时提供了一个参数来更改此行为,但不幸的是jQuery does not

当然,这意味着可以通过替换以下问题来轻松解决该问题:

$(document).on("touchmove",touchmove);

在我的代码中,加上:

document.addEventListener('touchmove', pageswiping.touchmove, {passive: false});

在这种情况下,{passive: false}清楚地表明事件侦听器是主动侦听器,而不是被动侦听器。