由于触摸事件

时间:2016-12-20 15:14:21

标签: javascript html css touch touch-event

如果您切换位于上方的元素的高度,则触摸设备上有关于链接的可点击区域的奇怪行为。如果您运行以下代码段(例如,在本地保存并使用chrome来模拟触摸事件),您会注意到在某些情况下您没有点击红色链接区域时,哈希#mylink会添加到网址中。有时你点击红色区域,它不会被添加。

E.g。

  • 如果单击上方灰色区域(前200px),灰色区域将切换高度。 =>确定。
  • 如果单击增强的较低灰色区域(200px - 400px),则会将#mylink添加到网址,就像您单击了红色链接区域一样。 =>为什么?
  • 如果单击上部红色区域(前200px,灰色区域最小化),则#mylink不会添加到网址中。 =>为什么?
  • 如果单击红色区域较低(最后200px,灰色区域增强),则#mylink不会添加到网址中。 =>为什么?

<html>
<head>
	<style type="text/css">
		.test {
			background: grey;
			height: 200px;
		}

		.test.is-visible {
			height: 400px;
		}

		.link {
			height: 600px;
			display: block;
			background: red;
		}
	</style>
	<script type="text/javascript">
	  (function() {
	    window.addEventListener( 'touchstart' , function() {
	    	document.getElementsByClassName("test")[0].classList.toggle('is-visible');
	    });	
		})();
	</script>
</head>

<body>
	<div class="test">
		Click the grey area. Element enhances and minimizes itself. Now click on the lower half of the enhanced grey area (if grey = enhanced) or on the white area up to 200px below of the red area (if grey = minimized). #mylink is added to the url as if you had clicked on the red area. Why?
	</div>
	<a href="#mylink" class="link">The red area is the "normal" click area.</a>
</body>

</html>

我在iOS和Android上尝试了这一功能,并在Chrome和Firefox中模拟了触控事件。他们都表现得一样。

如果我收听click而不是touchstarttouchend事件,则会按预期运行。

造成这种差异的原因是什么?如果我听触摸事件而不是点击事件,为什么链接区域不同/错位?

2 个答案:

答案 0 :(得分:4)

当您增强灰色区域并触摸下半部分时会发生这种情况:

  • 当您触摸灰色区域的下半部分时,会触发touchstart事件
  • 您的函数运行并切换(删除)灰色元素
  • 上的is-visible
  • 灰色元素的高度变小
  • 红色元素向上移动200px
  • 您的触摸没有移动,但页面上的元素有 - 您现在正在触摸红色元素
  • 当您释放触摸时,会在红色元素上触发touchend事件,这是确定链接是否被触及的事件

点击红色元素下面的区域200px时会发生同样的事情:

  • 当您触摸红色元素下方的区域时,会触发touchstart事件
  • 您的函数运行并切换(添加)灰色元素
  • 上的is-visible
  • 灰色元素的高度变大
  • 红色元素向下移动200px
  • 您的触摸没有移动,但页面上的元素有 - 您现在正在触摸红色元素
  • 当您释放触摸时,会在红色元素上触发touchend事件,这是确定链接是否被触及的事件

答案 1 :(得分:2)

<强> TL; DR

浏览器在touchend位置触摸事件后执行点击事件,无论内容是否因为分配给触摸事件的功能而发生变化。

在挖掘Touch Events specification后,我想我可以回答我的问题:

Section 8描述了触摸事件与鼠标事件的交互并单击。它说:

  

用户代理可以调度触摸事件和(...)鼠标事件以响应相同的用户输入。

  

如果用户代理将一系列触摸事件解释为点击手势,那么它应该在touchend事件的位置发送mousemove,mousedown,mouseup和click事件(按此顺序) 用于相应的触摸输入。

     

如果在处理触摸事件期间文档的内容具有改变,则用户代理可以将鼠标事件分派给与触摸事件不同的不同的目标。

最重要的

  

元素的激活(例如,在某些实现中,点击)通常会产生以下事件序列(尽管这可能略有不同,具体取决于特定的用户代理行为):

     

1。) touchstart

     

2。)零个或多个touchmove事件,取决于手指的移动

     

3。) touchend

     

4。)mousemove(与旧版鼠标特定代码兼容)

     

5.。mousedown

     

6。)mouseup

     

7。)点击

因此,总结上面的例子,这意味着:

1。)touchstarttouchend被触发。

2。)首先处理自定义函数,切换类并更改元素的高度/位置。

3.)之后,click事件在touch事件发生的同一点执行,但现在涵盖了不同的目标。

规范也提供了一种防止这种情况的方法:

  

如果取消touchstart,touchmove或touchend,则用户代理不应发送任何因阻止触摸事件而导致的鼠标事件。

所以我想“修复”这种行为的最简单方法是使用`preventDefault()'来阻止事件,然后手动点击事件的目标并最后切换类:

     window.addEventListener( 'touchstart' , function(event) {
        event.preventDefault();

        event.target.click();

        document.getElementsByClassName("test")[0].classList.toggle('is-visible');
    }); 

Chromium bug追踪器中有一个statement,证明了这一点。