移动触摸设备上是否有方法消除点击延迟?

9

在移动设备(如iPad、Galaxy Tab)上浏览网站时,当我点击一个元素(普通链接或使用javascript/jquery使可点击其他任何东西)时,总会出现延迟。

在网上阅读的过程中,我发现浏览器使用touchstart事件后跟随touchend事件,然后触发常规的click事件。是否有一种方式可以更快速地响应轻击并删除延迟的click事件?也许可以使用javascript或其他方法吗?

3个回答

5

这是一个源自Matt的库(https://dev59.com/2FPTa4cB1Zd3GeqPnerc#9370637),并经过Google代码改编的jQuery插件。

使用方式如下:$('mySelector').fastClick(handler);

(function($){
    var clickbuster = {
        preventGhostClick: function(x, y) {
          clickbuster.coordinates.push(x, y);
          window.setTimeout(clickbuster.pop, 2500);
        },
        pop: function() {
          clickbuster.coordinates.splice(0, 2);
        },
        onClick: function(event) {
          for (var i = 0; i < clickbuster.coordinates.length; i += 2) {
            var x = clickbuster.coordinates[i];
            var y = clickbuster.coordinates[i + 1];
            if (Math.abs(event.clientX - x) < 25 && Math.abs(event.clientY - y) < 25) {
              event.stopPropagation();
              event.preventDefault();
            }
          }
        }
    };


    var methods = {
        init: function(handler){
            return this.each(function() {
                var $this = $(this),
                    data = $this.data('fastClick');
                if(!data){
                    this.addEventListener('touchstart', methods.handleEvent, false);
                    this.addEventListener('click', methods.handleEvent, false);
                    $this.data('fastClick', {
                        target: $this,
                        handler: handler
                    });
                }
            });
        },
        handleEvent:function(event) {
          switch (event.type) {
            case 'touchstart': $(this).fastClick('onTouchStart',event); break;
            case 'touchmove': $(this).fastClick('onTouchMove',event); break;
            case 'touchend': $(this).fastClick('onClick',event); break;
            case 'click': $(this).fastClick('onClick',event); break;
          }
        },
        onTouchStart: function(event) {
          event.stopPropagation();
          this[0].addEventListener('touchend', methods.handleEvent, false);
          var _this = this;
          document.body.addEventListener('touchmove', function(event){
            methods.handleEvent.apply(_this,[event]);
          }, false);

          $(this).data('fastClick').startX = event.touches[0].clientX;
          $(this).data('fastClick').startY = event.touches[0].clientY;
        },
        onTouchMove: function(event) {
          if (Math.abs(event.touches[0].clientX - this.data('fastClick').startX) > 10 ||
              Math.abs(event.touches[0].clientY - this.data('fastClick').startY) > 10) {
              this.fastClick('reset');
          }
        },
        onClick: function(event) {
          event.stopPropagation();
          $(this).fastClick('reset');
          $(this).data('fastClick').handler.call(this,event);

          if (event.type == 'touchend') {
            clickbuster.preventGhostClick($(this).data('fastClick').startX, $(this).data('fastClick').startY);
          }
        },
        reset: function() {
          this[0].removeEventListener('touchend', methods.handleEvent, false);
          document.body.removeEventListener('touchmove', methods.handleEvent, false);
        }
    }
    $.fn.fastClick = function(method) {
        if (methods[method]) {
            return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
        } else if ( typeof method === 'object' || typeof method === 'function' || !method) {
            return methods.init.apply(this, arguments);
        } else {
            $.error('Method ' + method + ' does not exist on jQuery.hScroll');
        }

    }

    clickbuster.coordinates = [];
    document.addEventListener('click', clickbuster.onClick, true);

})(jQuery);

这似乎很酷,但我不知道如何知道自己点击了什么 - $(this) 不会返回你点击的东西,不像通常绑定事件。例如:$('a').fastClick(function(){alert($(this).attr('href'))}); 我该怎么做才能让它工作? - Rich Bradshaw
我也遇到了这个问题。我刚刚编辑了我的答案。onClick处理程序必须在正确的作用域中调用:handler.call(this,event)。请查看编辑。 - Armel Larcier
1
还有,现在还需要这个吗?我看到一些文章建议从Gingerbread开始,如果禁用viewport meta标签上的缩放,触摸就不会有延迟...你知道这方面的情况吗? - Rich Bradshaw
不知道安卓,但对于iOS仍然是必需的。 - Armel Larcier
在iOS上,你不是可以绑定到touch而不是click吗?我很确定touch没有延迟。 - Rich Bradshaw
显示剩余2条评论

2
如果您正在编写网页,可以为touchstart和touchend注册监听器,并直接从ontouchend触发onclick代码,而无需任何延迟。
如果您不在touchmove中处理事件,则浏览器将(有些滞后地)向元素分派click事件。
请查看谷歌的此描述,以创建“快速按钮”:http://code.google.com/intl/de-DE/mobile/articles/fast_buttons.html

如果您能发布一些代码来展示如何实现这一点,我们将不胜感激。在构建网站时,我通常使用jQuery,并且我知道可以使用.trigger()触发点击事件。但是我不知道如何在每次需要时自动调用“click”而无需手动添加... - Gabriel

0

我使用检测来判断设备是否支持触摸,就像现代化一样。如果是触摸设备,我会将一个名为touchClick的变量填充为选项'click''touchend',根据结果而定。在jQuery中,我只需调用:

 $('element').on(touchClick, function(e){ //do something });

它的占用空间非常小。


如果使用触摸屏笔记本电脑浏览器,这种方法是危险的。鼠标点击将无法正常工作... - franzlorenzon

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接