我有一些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);
答案 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}
清楚地表明事件侦听器是主动侦听器,而不是被动侦听器。