仅当手势尚未垂直滚动时,才允许水平平移事件

Permit horizontal pan events only if the gesture is not already scrolling vertically

本文关键字:许水平 水平 事件 滚动 垂直      更新时间:2023-09-26

我想设置 Hammer.js以便我可以响应水平平移事件。我的第一次尝试看起来像这样:

var mc = new Hammer(document.body);
mc.on("panleft panright", runBind(this, 'updatePosition'));
mc.on("panend", runBind(this, 'finalisePosition'));

这几乎得到了我正在寻找的行为:如果我向左或向右平移,则会调用updatePosition函数,当我停止平移时,将调用finalisePosition函数。

但是,如果垂直滚动时手势向左或向右漂移,也会触发这些功能。例如,假设我在屏幕顶部附近触摸,然后将手指向下拖动屏幕的一半:这应该注册为滚动事件。现在假设我继续沿对角线拖动:向下和向左拖动。在这种情况下,我想忽略手势的水平部分,仅将手势视为垂直滚动事件,但 Hammer.js 像以前一样触发panrightpanleft事件。

我的下一次尝试如下所示:

var mc = new Hammer(document.body, {
  recognizers: [
    [Hammer.Swipe],
    [
      Hammer.Pan,
      {event: 'panvertical', direction: Hammer.DIRECTION_VERTICAL}
    ],
    [
      Hammer.Pan,                               // RecognizerClass
      {direction: Hammer.DIRECTION_HORIZONTAL}, // options
      ['swipe'],                                // recognizeWith
      ['panvertical']                           // requireFailure
    ],
  ]
});
mc.on("panleft panright", runBind(this, 'updatePosition'));
mc.on("panend", runBind(this, 'finalisePosition'));

这指定仅当panvertical事件失败时,才应触发水平平移事件。果然,这可以防止我上面描述的问题。如果我开始垂直滚动手势,然后开始水平移动,则不会触发panleftpanright事件。但是这个版本有一个更严重的问题:默认的滚动行为不会发生!因此,无法滚动应用程序。

谁能提出更好的解决方案?

我使用的是 Hammer.js 2.0.4 版。

我遇到了同样的问题,并且我已经设法让它与这个非常丑陋的代码一起工作

   var first = false, lock = false;
   var containerHandler = function(event) {
       if(event.type == 'panend' || event.type == 'pancancel') {
         // iOS bug fix
         lock = false;
         first = false;
       } else if(event.type == 'swipe' && event.direction & Hammer.DIRECTION_VERTICAL) {
         // iOS bug fix
         lock = true;
         first = true;
       }
       else if(event.type == 'panmove') {
         // iOS bug fix ... 
         if(first === false && event.direction & Hammer.DIRECTION_VERTICAL) {
           lock = true;
         }
         first = true;
         if(lock === true)
         return;
         //your code etc...
    };
    var focusMC = new Hammer.Manager(mainContainer[0], {domEvents:true});
    var pan = new Hammer.Pan({threshold: 5, direction:Hammer.DIRECTION_HORIZONTAL});
    focusMC.add( pan );
    focusMC.on('panstart panmove panend pancancel swipe', containerHandler);

小阈值很重要。

据我所知,此问题仅在iOS Safari上,但是在WP上即使没有此代码,它也可以正常工作

编辑:尝试强制使用 touch-action 属性,而不是上面的解决方案到pan-y

我保留了两个答案,因为它们都应该有效

Hammer.js将根据识别器自动推断触摸操作属性。这可能会使应用程序的响应速度更快,但它不会仅仅因为用户与元素交互而阻止垂直页面滚动。

我遇到了与您相同的问题,并找到了一个非常简单的解决方案,该解决方案非常适合解决方法。

var isScrolling = false;
var galleryHammer = new Hammer(element, {
    recognizers: [
        [Hammer.Pan, { direction: Hammer.DIRECTION_HORIZONTAL }]
    ]
});
// Making the event listener passive means we don't get any delays between
// the user scrolling and the browser having checked if it should prevent
// that event
window.addEventListener('scroll', function() {
    isScrolling = true;
}, { passive: true });
window.addEventListener('touchend', function() {
    isScrolling = false;
});
galleryHammer.on('pan', function(event) {
    if (isScrolling) {
        return;
    }
    // Normal logic...
});
这对

我有用(代码来自一个类,this.hm 只是一个 Hammer 实例):

this.hm.on('panleft', function(e){ // ...and same for panright
   if(e.pointerType == 'touch' && (Math.abs(e.deltaY) > Math.abs(e.deltaX))){ return false; }
   // do stuff
}

额外的指针类型检查在那里,因为我在台式计算机上没有任何问题(鼠标事件)。因此,整体应用于触摸设备/事件。