繁体   English   中英

有没有办法防止fastclick在滚动时触发“活动”状态?

[英]Is there a way to prevent fastclick from firing “active” state on scroll?

我在具有大链接的页面上使用FastClick ,因为我想在移动浏览器中绕过300ms的点击延迟。 我有一个“突出”样式的链接' :active状态,它正在快速正确触发,感谢FastClick。

我的问题是 - 至少在Mobile Safari中 - 当你点击和滑动以滚动页面时它也会触发。 这使得您觉得无法在不考虑点击链接的情况下滚动页面。

当有人滚动时,有没有办法阻止它发射?

也许你可以将needsclick类添加到正文中?

<body class="needsclick">

...

</body>

只是一个想法:)

好问题! +1

此问题与FastClick无关,但FastClick确实使您的问题的解决方案更加复杂。 所以我将坚持纯JavaScript和原始触摸事件)

在移动触摸设备上,由于特定于平台的原因,webview的实现与桌面web浏览器显着不同。 在这种情况下,一个重要的功能是webview中的动量滚动。 Momentum Scrolling是设备的硬件加速功能。 因此,当在屏幕上触摸可滚动区域时,硬件识别触摸并将200毫秒倒数计时器附加到可滚动区域,当触发时,将该区域置于硬件加速滚动中。 当硬件处于状态时,它不会广播触摸事件,因为它们特定于硬件加速滚动。 可以取消计时器,并通过在提供的200毫秒内对触摸事件使用preventDefault来防止动量滚动。

这是我如何处理这个问题。 我假设您正在使用本机滚动即overflow:scroll 该方法是将touchstart事件附加到您想要可触摸的元素。 touchstart事件触发后,事件处理程序touchendtouchmovetouchcancel事件附加到目标元素。 启动setTimout计时器,在140ms后删除新添加的事件。

以下是我的生产代码的一些剪辑:我有两种事件方法可以添加和删除集合中的事件:

var eventify = (function () {
    function eventify(type, el, callback, phase) {
        phase = phase || false;
        if ((el.constructor.toString().contains('NodeList')) || (el.constructor.toString().contains('HTMLCollection'))) {
            [].forEach.call(el, function (element) {
                if (!element.hasEvent(type)) {
                    element.addEvent(type);
                    HTMLElement.prototype.addEventListener.apply(element, [type, callback, phase]);
                }
            });
        } else {
            if (!el.hasEvent(type)) {
                el.addEvent(type);
                HTMLElement.prototype.addEventListener.apply(el, [type, callback, phase]);
            }
        }
        return callback;
    }

    return eventify
})();

var uneventify = (function () {
    function uneventify(type, el, callback) {
        if ((el.constructor.toString().contains('NodeList')) || (el.constructor.toString().contains('HTMLCollection'))) {
            [].forEach.call(el, function (element) {
                if (element.hasEvent(type)) {
                    element.removeEvent(type);
                    HTMLElement.prototype.removeEventListener.apply(element, [type, callback]);
                }
            });
        } else {
            if (el.hasEvent(type)) {
                el.removeEvent(type);
                HTMLElement.prototype.removeEventListener.apply(el, [type, callback]);
            }
        }
    }

    return uneventify
})();

然后我在滚动条上有一个tapify方法来点击事件:

var tapify = (function () {
    function tapify(el, callback) {
        eventify('touchstart', el, function (e) {
            var that = this;
            var start = e.pageY;
            var target = e.target;
            function dynamicEvents() {
                var endfn = eventify('touchend', target, function (evt) {
                    e.preventDefault();
                    e.stopImmediatePropagation();
                    evt.preventDefault();
                    evt.stopImmediatePropagation();
                    uneventify('touchmove', target, movefn);
                    uneventify('touchend', target, endfn);
                    uneventify('touchcancel', target, cancelfn);
                    callback && callback(target);
                });
                var cancelfn = eventify('touchcancel', target, function (evt) {
                    e.preventDefault();
                    e.stopImmediatePropagation();
                    evt.preventDefault();
                    evt.stopImmediatePropagation();
                    uneventify('touchmove', target, movefn);
                    uneventify('touchend', target, endfn);
                    uneventify('touchcancel', target, cancelfn);
                    callback && callback(target);
                });
                var movefn = eventify('touchmove', target, function (evt) {
                    var distance = start - evt.pageY;
                    if (distance > 20) {
                        uneventify('touchend', target, endfn);
                        uneventify('touchcancel', target, cancelfn);
                        uneventify('touchmove', el, movefn);
                    }
                });
                setTimeout(function () {
                    uneventify('touchmove', target, movefn);
                    uneventify('touchend', target, endfn);
                    uneventify('touchcancel', target, cancelfn);
                }, 140);
            }
            if (global.isIos) setTimeout(function () {
                dynamicEvents();
            }, 60);
            else dynamicEvents();
        }, false);
    }
    return tapify;
})();

我使用global.isIos来识别目标设备。 Android会停止向webview发送触摸事件200ms。

然后,要将事件附加到元素或元素集合,请使用:

tapify(document.querySelectorAll('button'), function (e) {
      //your event handler here!! 
});

希望这可以帮助

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM