IE Edge上的跨框架事件打破了HammerJS(v2)

时间:2016-02-25 04:06:29

标签: javascript-events hammer.js pointer-events

我正面临一个奇怪的问题,我认为会让HammerJS内部事件循环出现卡住事件,导致后续检测失败。

这只发生在使用PointerEvents的触控设备上的Internet Explorer Edge上

基本上,当HammerJS用于PAN事件(panstart - > panmove - > panend)时,你越过当前帧边界(例如,进入IFRAME,或者只是在浏览器窗口之外)你将手指放在那里,然后HammerJS从未收到CANCEL事件,会话类型仍然卡住。

从那时起,所有手势都被错误地报告,还有一个手指(“指针”)而不是你正在使用:例如,它会报告PINCH或ROTATE(2个指针)点击(1指针)等等。

一旦进入鬼状态,我还没有找到重置Hammer Manager的方法。这打破了我的应用。

我准备了一个完整的工作示例的小提琴。请在Windows / Touch设备下执行!

enter image description here

https://jsfiddle.net/28cxrupv/5/

我想知道,如果我能通过其他方式检测到自己,如何检测越界事件,或者如何手动重置Hammer Manager实例有卡住的事件。

更新

我在调查中发现问题出现在HammerJS的最低级别:PointerEvents处理程序有一个检测到的指针数组this.store,而且卡住的事件带有旧的时间戳。

1 个答案:

答案 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 = []);
        },