0

我面临一个奇怪的问题,我认为 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并且有一个带有旧时间戳的卡住事件。

4

1 回答 1

0

我找到了一种修补 Hammer.JS 的方法,以便它可以检测到卡住的指针。我不知道这是否是错误的,但显然它有效!

在 HammerJS PointerEvents 处理程序上,有一个数组this.store保存所有当前的指针事件。它就在那里,当我们平移出窗口并释放触摸时,卡住的事件将永远保留。

清除此数组会导致 Hammer 再次恢复正常。

我刚刚添加了一个条件,如果我们正在处理主要触摸(手势开始?),并且存储不是空的,它会自动清除存储。

它的工作原理是,在与卡住的锤子实例的下一次交互中,内部存储被重置并且手势被正确解释。

在 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 internal state
         */

        reset: function() {
            this.store = (this.manager.session.pointerEvents = []);
        },
于 2016-02-25T18:50:22.397 回答