我正面临一个奇怪的问题,我认为会让HammerJS内部事件循环出现卡住事件,导致后续检测失败。
这只发生在使用PointerEvents的触控设备上的Internet Explorer Edge上。
基本上,当HammerJS用于PAN
事件(panstart
- > panmove
- > panend
)时,你越过当前帧边界(例如,进入IFRAME,或者只是在浏览器窗口之外)你将手指放在那里,然后HammerJS从未收到CANCEL事件,会话类型仍然卡住。
从那时起,所有手势都被错误地报告,还有一个手指(“指针”)而不是你正在使用:例如,它会报告PINCH或ROTATE(2个指针)点击(1指针)等等。
一旦进入鬼状态,我还没有找到重置Hammer Manager的方法。这打破了我的应用。
我准备了一个完整的工作示例的小提琴。请在Windows / Touch设备下执行!
https://jsfiddle.net/28cxrupv/5/
我想知道,如果我能通过其他方式检测到自己,如何检测越界事件,或者如何手动重置Hammer Manager实例有卡住的事件。
更新
我在调查中发现问题出现在HammerJS的最低级别:PointerEvents处理程序有一个检测到的指针数组this.store
,而且卡住的事件带有旧的时间戳。
答案 0 :(得分:0)
我找到了一种修补Hammer.JS的方法,因此它可以检测卡住的指针。我不知道这是不是错了,但显然它有效!
在HammerJS PointerEvents处理程序中,有一个数组this.store
可以保存所有当前指针事件。它就在那里,当我们从窗户向外平移并释放触摸时,卡住的事件将永远存在。
清除此数组会导致Hammer再次恢复正常。
我刚刚添加了一个条件,如果我们正在处理主要触摸(开始手势?),并且商店不为空,它会自动清除商店。
它是如何工作的,在与卡住的锤子实例的下一次交互中,内部存储被重置并且手势被正确解释。
On Hammer.js 2.0.6,885行左右
/**
* handle mouse events
* @param {Object} ev
*/
handler: function PEhandler(ev) {
var store = this.store;
var removePointer = false;
var eventTypeNormalized = ev.type.toLowerCase().replace('ms', '');
var eventType = POINTER_INPUT_MAP[eventTypeNormalized];
var pointerType = IE10_POINTER_TYPE_ENUM[ev.pointerType] || ev.pointerType;
var isTouch = (pointerType == INPUT_TYPE_TOUCH);
// get index of the event in the store
var storeIndex = inArray(store, ev.pointerId, 'pointerId');
// start and mouse must be down
if (eventType & INPUT_START && (ev.button === 0 || isTouch)) {
// NEW CONDITION: Check the store is empty on a new gesture
// http://stackoverflow.com/questions/35618107/cross-frame-events-on-ie-edge-break-hammerjs-v2
if (ev.isPrimary && store.length) {
window.console.warn ("Store should be 0 on a primary touch! Clearing Stuck Event!");
this.reset();
}
if (storeIndex < 0) {
store.push(ev);
storeIndex = store.length - 1;
}
} else if (eventType & (INPUT_END | INPUT_CANCEL)) {
removePointer = true;
}
// it not found, so the pointer hasn't been down (so it's probably a hover)
if (storeIndex < 0) {
return;
}
// update the event in the store
store[storeIndex] = ev;
this.callback(this.manager, eventType, {
pointers: store,
changedPointers: [ev],
pointerType: pointerType,
srcEvent: ev
});
if (removePointer) {
// remove from the store
store.splice(storeIndex, 1);
}
}
});
我还定义了“reset”函数:
/**
* Reset internal state
*/
reset: function() {
this.store = (this.manager.session.pointerEvents = []);
},