Safari无法触发触摸事件

16

我有一个小的jsfiddle示例 - http://jsfiddle.net/qhguktsn/5/。在顶部文本处点击链接(iOS移动Safari),你只能获得鼠标事件 - 没有触摸事件,甚至没有在body上触发。如果你在文本底部点击它,你会得到触摸事件。我们依赖于触摸事件来处理300毫秒延迟。

我们如何在文本顶部和底部都获取触摸事件?

HTML:

<div style="margin-left:200px;margin-top:200px">
    <a style="vertical-align:center;height: 20px, width: 20px;font-size:100px" href="javascript: void 0">text</a>
</div>

JS:

jQuery("a").on("mousedown", function() { document.body.appendChild(document.createTextNode("mousedown ")); });
jQuery("a").on("mouseup", function() { document.body.appendChild(document.createTextNode("mouseup ")); });
jQuery("a").on("touchstart", function() { document.body.appendChild(document.createTextNode("touchstart ")); });
jQuery("a").on("touchend", function() { document.body.appendChild(document.createTextNode("touchend ")); });
jQuery("a").on("click", function() { document.body.appendChild(document.createTextNode("click ")); });

jQuery(document.body).on("touchstart", function() { document.body.appendChild(document.createTextNode("body touchstart ")); });
jQuery(document.body).on("touchend", function() { document.body.appendChild(document.createTextNode("body touchend ")); });

我认为我可能在iOS 8.1.2上使用Chrome遇到了同样的问题。 - user5257014
Chrome在iOS上使用与Safari相同的渲染引擎,因此行为应该是相同的(所有其他在iOS上运行的浏览器也应该如此)。 - Luckyrat
我一直在努力找出为什么我的小按钮的触摸事件不能始终触发,而您的帖子帮助我了解到这是一个边缘问题!只要您点击得太靠近任何边缘(包括左侧和右侧边缘),触摸事件就会失败,但单击事件仍然可以触发。 - Kevin Lee
在安卓版的Chrome中有相同的问题。 - Kevin Lee
使用jQuery Mobile的“tap”事件进行了测试。即使触摸开始没有触发,“tap”事件似乎也会在边缘触发。不确定原因。可能需要进一步探索。 - Kevin Lee
3个回答

12

这是移动版Safari中的已知问题。 https://bugs.webkit.org/show_bug.cgi?id=105406 还有另一个问题,是从不同文档添加节点时出现的。 https://bugs.webkit.org/show_bug.cgi?id=135628

为了修复它们,有几种方法。

  • 第一种方法是使用一个名为 fastclick 的小型库,它支持许多移动设备和操作系统。

  • 第二个选项是像这样添加 event.stopPropagation(); event.preventDefault();。你两个都需要。

jQuery("a").on("mousedown", function(event) {
    event.stopPropagation();
    event.preventDefault();
    document.body.appendChild(document.createTextNode("mousedown ")); 
});
  • 第三种选项是使用视口元标记,例如<meta name="viewport" content="width=device-width, user-scalable=no">。这将消除所有触摸延迟,无需任何解决方法。但是,在Safari浏览器上可能不像其他浏览器那样运行,因为嘿,Safari是新的IE

  • 还有touch-action,但它在大多数移动浏览器中都不受支持。 :(


    我对这个 bug 并不是很有信心,因为我们在按钮上点击的位置不同会导致不同的行为。而你列出的修复方法并不适用。Fastclick 只是做了和我们一样的事情,我真的不确定取消鼠标事件会如何让前面的触摸事件神奇地出现,而你所说的第三个选项也不适用于 Safari,所以我真的看不到它的相关性。 - Puppy
    抱歉我无法提供更多帮助。目前我没有更多的想法。 - Stanimir Dimitrov
    顺便提一下,检查一下这篇文章底部的链接。https://dev59.com/2VDTa4cB1Zd3GeqPIFTk#4165641 - Stanimir Dimitrov

    2

    我发现当点击一个被定位为fixed的元素时,如果该元素超出窗口范围,触摸事件将不会被触发。我通过使父容器变短(使用JS获取确切的窗口高度)来解决这个问题。

    这个问题出现在使用iOS 10的app UIWebview中。(是的,仍在使用UIWebview)


    2
    上的触摸事件是由于元素通过margin-top向下移动,给元素加上轮廓线可以突出触摸目标:
    body { outline: 1px solid red; }
    

    http://jsfiddle.net/qhguktsn/11/

    谜题的第二部分似乎是点击目标在触摸目标外扩展:

    文本截图

    触摸红色轮廓不会在 body 元素上触发触摸事件,但点击事件似乎会在灰色的 -webkit-tap-highlight-color 区域内的任何地方触发,该区域超出了锚点本身。因此,顶部的轻敲将在锚点上触发单击事件,但不会在 body 上触发触摸事件。


    这里的主要问题是受影响的区域太小了 - 在实际测试中,顶部有一个明显更大的带状区域出现了问题。 - Puppy
    似乎浏览器总是将点击位置解释为比用户实际点击的位置要高得多,所以这两个问题之间可能存在关联。 - Puppy
    @道格拉斯,感谢您为这个谜题提供了一些线索。是否有解决这个问题的办法? - Kevin Lee

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