消除移动Safari中点击事件的300ms延迟


88

我了解到,从单击链接/按钮到事件触发之间,移动Safari的点击事件会延迟300毫秒。延迟的原因是等待用户是否打算双击,但是从UX的角度来看,等待300ms通常是不希望的。

消除这种300毫秒延迟的一种解决方案是使用jQuery Mobile“点击”处理。不幸的是,如果我只需要touchend以正确的方式应用一两行代码,我就不会熟悉这个框架,也不想加载一些大型框架。

像许多网站一样,我的网站也有许多如下点击事件:

$("button.submitBtn").on('click', function (e) {   
  $.ajaxSubmit({... //ajax form submisssion
});

$("a.ajax").on('click', function (e) {   
  $.ajax({... //ajax page loading
});

$("button.modal").on('click', function (e) {   
      //show/hide modal dialog
});

而我想做的就是使用一个简单的代码片段消除所有这些单击事件的300ms延迟:

$("a, button").on('tap', function (e) {
 $(this).trigger('click');
 e.preventDefault();
});

这是一个好主意吗?



@Pointy谢谢,这可能行得通...
蒂姆·彼得森

“ ...显然,从用户体验的角度来看,这不是很好。” 我会对这个假设保持警惕。
奥利弗·莫兰

1
@OliverMoran,感谢您的修正,我只是编辑的那句话,见上面..这个问题
蒂姆·彼得森

Answers:


72

现在,如果您设置了视口,则某些移动浏览器可以消除300毫秒的单击延迟。您不再需要使用变通办法。

<meta name="viewport" content="width=device-width, user-scalable=no">

这是目前支持Android版ChromeAndroid版FirefoxSafari浏览器适用于iOS

但是,在iOS Safari上,双击是不可缩放页面上的滚动手势。因此,他们无法消除300ms的延迟。如果他们无法消除不可缩放页面上的延迟,则不太可能消除不可缩放页面上的延迟。

Windows Phone在无法缩放的页面上也保留了300ms的延迟,但是它们没有像iOS这样的替代手势,因此有可能像Chrome一样消除这种延迟。您可以使用以下方法消除Windows Phone上的延迟:

html {
-ms-touch-action: manipulation;
touch-action: manipulation;
}

来源:http : //updates.html5rocks.com/2013/12/300ms-tap-delay-gone-away

2015年12月更新

直到现在,iOS上的WebKit和Safari都有350ms的延迟,而单击则无法激活链接或按钮,从而使人们可以双击来放大页面。Chrome在几个月前已经通过使用更智能的算法来检测到这一点,从而改变了这一点,WebKit将采用类似的方法。本文提供了一些很好的见解,说明浏览器如何使用触摸手势,以及如何使浏览器变得比今天更加智能。

2016年3月更新

在iOS的Safari上,删除了检测第二次敲击的350毫秒等待时间,以创建“快速敲击”响应。对于使用width = device-width或user-scalable = no声明视口的页面启用此功能。作者可以选择同时在通过使用CSS的特定元素的快速抽头行为,touch-action: manipulation如记录在这里 (向下滚动到“样式化快速点击行为”标题下),并在这里



1
是的,正如我在帖子中所写的那样,它由-ms-touch-action控制。
NoName

1
从主页(独立)运行应用程序时,iOS上仍然存在问题。如果有人找到了合适的解决方法,那将是非常受欢迎的
Miguel Guardo

1
将触摸动作值设置为可操作的操作最接近所需的性能,但是正如@MiguelGuardo先前所述,将网页作为独立应用程序添加到iOS的主屏幕后,效果会消失。
T. Steele

可能有人能破解的UIWebView - stackoverflow.com/questions/55155560/...
EAZY

43

由金融时报开发的此插件-FastClick 非常适合您!

确保添加 event.stopPropagation();event.preventDefault();在click函数之后和/或直接它,否则它可能会为我运行两次,即:

$("#buttonId").on('click',function(event){
    event.stopPropagation(); event.preventDefault();
   //do your magic

});

3
如果您使用的是jquery mobile(无论如何为1.3.2版),则这并不完美,它会中断面板小部件的关闭github.com/jquery/jquery-mobile/issues/6440
ryan0

该event.stopPropagation()正是我首先来到此页面的原因。完美运行,谢谢!
卢卡斯2014年

@Jonathan fastclick仅在存在延迟问题(否则会自动绕过)的触摸设备上发挥作用。但是,在每个click事件之后简单添加stopPropagationpreventDefault可能会对所有浏览器中的所有事件处理程序产生有害的副作用。
用户

17

我知道这已经很老了,但是您不能只测试一下浏览器是否支持“触摸”吗?然后创建一个“ touchend”或“ click”变量,并将该变量用作绑定到您的元素的事件?

var clickOrTouch = (('ontouchend' in window)) ? 'touchend' : 'click';
$('#element').on(clickOrTouch, function() {
    // do something
});

因此该代码示例检查浏览器是否支持“ touchend”事件,如果不支持,则使用“ click”事件。

(编辑:将“ touchend”更改为“ ontouchend”)


谢谢,我喜欢这个简单。我希望其他人对它的可能陷阱有所了解。
蒂姆·彼得森

4
由于@AndreasKöberle在回覆中说明,touchend事件无法取代点击事件。例如,如果您滚动并且手指停在按钮上,它将触发链接...
adriendenat

这是一个很棒的轻量级解决方案,而不必为了避免延迟而添加大量额外的东西。希望我能对此投票最多5次!(只要您不担心滚动情况!)
tonejac 2014年

2
对于具有触摸和单击事件支持的计算机/浏览器,这是一个糟糕的解决方案。
亚历山大·奥玛拉2014年

1
某些设备同时支持触摸和单击事件,并且您希望它们在不同情况下都触发。我们遇到过这样的情况:某些带有鼠标的Windows或android平板电脑显然会在您单击某物时触发click事件,但在您点击时也会触发touch事件。这意味着您必须聆听这两个事件。另一个复杂的因素是,某些设备在您点击时会合成click事件,因此,除非您小心,否则在这些设备上同时收听这两个事件可能会导致事件处理程序触发两次。
1800信息

12

我遇到了一个非常受欢迎的替代品,称为Hammer.js (Github页面),我认为这是最好的方法。

与Fastclick.js(最受好评的答案)相比,Hammer.js是功能更全的触摸库(具有许多滑动命令)。

但是要当心:使用Hammer.js或Fastclick.js时,在移动设备上快速滚动往往会真正锁定UI。如果您的站点具有新闻源或用户将滚动很多的界面(这似乎是大多数Web应用程序),则这是一个主要问题。由于这个原因,我目前没有使用这两个插件。


2
不要使用Hammerjs。它有一些严重的问题,例如:github.com/EightMedia/hammer.js/issues/388 github.com/EightMedia/hammer.js/issues/366 至少在修复后才使用它
AdonisK。 Kakoulidis

2

不知何故,禁用缩放似乎会禁用此小的延迟。很有道理,因为那时不再需要双击。

如何“禁用”移动网页的缩放?

但是请注意这将对可用性产生影响。它对于设计为应用程序的网页很有用,但不应用于更通用的“静态”页面恕我直言。我将其用于需要低延迟的宠物项目。


1

不幸的是,没有简单的方法可以做到这一点。因此,仅使用touchstarttouchend会给您带来其他问题,例如,例如,单击某个按钮时有人开始滚动。我们使用zepto已有一段时间,即使有了这个非常好的框架,随着时间的流逝仍会出现一些问题。他们很多都关门了,但这似乎不是简单解决方案的领域。

我们提供了以下解决方案来全局处理链接的点击:

   $(document.body).
    on('tap', 'a',function (e) {
      var href = this.getAttribute('href');
      if (e.defaultPrevented || !href) { return; }
      e.preventDefault();
      location.href= href;
    }).
    on('click', 'a', function (e) {
      e.preventDefault();
    });

-@ Andreas,谢谢,所以您会提倡不要使用tap我发布的一般解决方案,而应将tap事件逐个要素分解?
蒂姆·彼得森(2012年

不,那不是重点。关键不是要tap自己构建解决方案。我将更新我的答案。
AndreasKöberle2012年

-@ Andreas,感谢您的回答,许多单击事件都是AJAX,因此已经阻止了默认事件。您介意也更新您的答案来处理吗?tap在这种情况下,我的一般解决方案似乎与您的解决方案相同?
蒂姆·彼得森(2012年

1

我搜索了没有jquery和没有fastclick库的简单方法。这对我有用:

var keyboard = document.getElementById("keyboard");
var buttons = keyboard.children;
var isTouch = ("ontouchstart" in window);
for (var i=0;i<buttons.length;i++) {
    if ( isTouch ) {
        buttons[i].addEventListener('touchstart', clickHandler, false);         
    } else {
        buttons[i].addEventListener('click', clickHandler, false);          
    }
}

0

仅提供一些额外的信息。

在iOS 10上, <button>无法连续触发我页面上的。总会有一个滞后。

我尝试了fastclick / Hammer / tapjs /用touchstart代替click,但都失败了。

更新:原因似乎是按钮太靠近边缘了!将其移到中心附近,然后消失!


0

您应该显式声明被动模式

window.addEventListener('touchstart', (e) => {

    alert('fast touch');

}, { passive : true});

0

在jQuery中,您可以绑定“ touchend”事件,点击后立即触发代码(就像键盘上的按下键一样)。在当前的Chrome和Firefox平板电脑版本上进行了测试。对于触摸屏笔记本电脑和台式机设备,也不要忘记“单击”。

jQuery('.yourElements').bind('click touchend',function(event){

    event.stopPropagation();
    event.preventDefault();

	// everything else
});

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.