我想设置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会像以前一样触发panright
和panleft
事件。 / p>
我的下一次尝试看起来像这样:
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
事件失败时才触发水平平移事件。果然,这可以防止我上面描述的问题。如果我开始垂直滚动手势然后开始水平移动,则不会触发panleft
和panright
事件。但是这个版本有一个更严重的探测:默认的滚动行为不会发生!因此,无法滚动应用程序。
有人能提出更好的解决方案吗?
我正在使用Hammer.js版本2.0.4。
答案 0 :(得分:0)
我遇到了同样的问题 我设法使用这个非常丑陋的代码
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
我保留两个答案,因为它们应该全部工作
答案 1 :(得分:0)
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...
});
答案 2 :(得分:0)
这对我有用(代码来自一个类,而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
}
因为我在台式机上没有任何问题(鼠标事件),所以进行了额外的pointerType检查。因此,整个过程仅适用于触摸设备/事件。