1. 前言
最近看了一本《移动Web手册》的书,奇舞团翻译的,非常不错。个人觉得在进入移动端的时候最先应该了解移动端新的交互模式:触摸。为什么这样说呢?在PC端,我们大多数的交互都是通过鼠标来实现,在开发过程中,对鼠标事件的处理也非常多,通过之前在移动端的开发经验,在移动端的交互也避免不了经常与触摸打交道,所以我们有必要单独学习一下它。
2. 触摸、鼠标交互模式
(1) 连续性
触摸事件是不连续的,鼠标事件是连续的。
操作顺序:A -> B -> C
在鼠标上:鼠标点击A -> 划过B -> 点击C
在触摸上:手指触摸A -> 跨过B -> 触摸C
(2) 下一步预期的操作
在鼠标上:移入元素 -> 点击鼠标左键 -> 触发单击 -> 在有效时间内点击第二次 -> 触发双击
在触摸上,可能有以下几种情况:
- 手指触摸屏幕 -> 轻触
- 手指触摸屏幕 -> 双触
- 手指触摸屏幕 -> 滑动
- 手指触摸屏幕 -> 缩放
其实作者认为鼠标事件在用户点击的时候就能够判断行为,其实我觉得如果是双击事件的情况下,浏览器也需要等待一段时间才能够做出反应。这个可以查阅一下google。
(3) 等价事件
3. 单说触摸事件
在了解两种不同的交互模式的基础上,我们再来进行单个的分析。其实我觉得学习一样东西,最根本的还是摸清原理部分,就能够很快的Get它了,当然,编码量不够的情况下也许还是需要慢慢来,掌握得更加扎实。
(1) 事件种类
- touchstart: 手指触摸屏幕的瞬间
- touchmove: 手指在屏幕上移动的时候
- touchend: 手指离开屏幕的时候
- touchcancel
其实从命名上就能很清楚的明白他们是干嘛的,当然,有一个比较特殊:touchcancel事件,可能会不太好理解,在最初的学习中可以忽略它,这里做一个简单的介绍:
touchcancel 在系统发生中断的时候会触发,这样说很抽象,我们来举一个栗子,比如你正在玩游戏,触摸的时候,突然手机来了一条短信,这个时候短信通知这个更高级的事件中断了触摸操作,touchcancel事件就触发了。在这个时候游戏开发中,会使用它来进行暂停游戏等操作。
由于touchcancel触发的时机不好掌控,所以一般情况下我们会采用下面的方式来处理touchcancel,维护我们的代码逻辑,当然这个要看业务场景。
dom.addEventListener('touchcancel', function(e){
e.preventDefault();
}, false);
(2) 触发时机
介绍完了事件的种类,我们来对每一种事件都进行代码级别的测试,看一看是否跟它说的先后顺序一样,这里我将引入鼠标事件一起测试,因为有一些区别性的东西哦。
我们先看一下测试结果:(iOS 8.3 Safari)
A.直接触摸空白部分,然后直接离开
B.在空白区域触摸并滑动,然后离开
C.点击界面中的按钮,未阻止冒泡
D.点击界面中一块区域,阻止冒泡
E.长按屏幕空白部分,出现选中效果,然后立刻离开屏幕
结果很明了,就不需要总结了,下面我们看一下测试的代码:
DOM
<div>
<button class="btn">这里是一个按钮</button>
<span class="area">这里是一块可点击区域</span>
<p class="info"></p>
</div>
JavaScript
;(function () {
var doc = document;
var info = doc.querySelector('.info');
var btn = doc.querySelector('.btn');
var area = doc.querySelector('.area');
doc.ontouchstart = function (e) {
info.innerHTML += ', '+ e.type;
}
doc.ontouchmove = function (e) {
info.innerHTML += ', '+ e.type;
}
doc.ontouchend = function (e) {
info.innerHTML += ', '+ e.type;
}
doc.ontouchcancel = function (e) {
info.innerHTML += ', '+ e.type;
}
doc.onmouseover = function (e) {
info.innerHTML += ', '+ e.type;
}
doc.onmousemove = function (e) {
info.innerHTML += ', '+ e.type;
}
doc.onmousedown = function (e) {
info.innerHTML += ', '+ e.type;
}
doc.onmouseup = function (e) {
info.innerHTML += ', '+ e.type;
}
doc.onmouseleave = function (e) {
info.innerHTML += ', '+ e.type;
}
doc.onclick = function (e) {
info.innerHTML += ', document: '+ e.type;
}
btn.onclick = function (e) {
info.innerHTML += ', button: '+ e.type;
}
area.onclick = function (e) {
e.stopPropagation();
info.innerHTML += ', area: '+ e.type;
}
})();
CSS
.btn {
width: 100%;
height: 60px;
line-height: 60px;
font-size: 16px;
border: none;
color: #fff;
text-align: center;
background: #2A3846;
}
.area {
display: block;
width: 100%;
height: 60px;
line-height: 60px;
color: #fff;
text-align: center;
background: #2A3846;
margin-top: 20px;
}
为了不干扰直接知识的理解,之前没有说不同meta头的事情,以及Safari与UC浏览器之间的差异。毕竟要接地气嘛,UC还是要测试一下的。
情况一
<meta name="viewport" content="width=device-width">
行为:“触摸空白区域,立刻离开时候的现象”
现象:
Safari:touchstart与touchend事件触发后,延迟一段时间,触发mouse以及click事件;
UC:只触发了touchstart与touchend事件,并无触发mouse和click事件。
行为:“点击页面的按钮(或者元素区域),立刻离开时候的现象”
现象:
Safari:touchstart与touchend事件触发后,延迟一段时间,触发mouse以及click事件,不过click触发是从按钮到document的顺序;
UC:与Safari中表现一致。
总结:
- 如果没有禁止缩放,Safari和UC中的点击事件均有延迟现象;
- 在document上绑定事件,与其他元素上绑定事件上述两个浏览器之间存在差异。
情况二
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
先不考虑这样写不符合单一变量测试原则,国内移动网站大多都是这样的meta头,当然,我有测试过,只要带有user-scalable一项就能够满足下面的实验。
不过下面的实验我们排除“点击空白区域这种情况”,因为这document绑定事件确实有差异,我们只测试“点击按钮”这一种行为。
行为:“点击页面的按钮(或者元素区域),立刻离开时候的现象”
现象:
Safari:touchstart与touchend事件触发后,延迟一段时间,触发mouse以及click事件,不过click触发是从按钮到document的顺序;
UC:touchstart、touchend、mouse、click先后顺序不变,但是几乎是同时触发,没有发生延迟。
总结:
在这种情况下,Safari依然存在click事件延迟,UC不存在延迟。
好吧,我承认这样实验有点枯燥,但是必须得这样才能弄明白到底怎么了,到底是怎么了。。。
Tip:这里赞美一下Safari,它能够很好的监听touchmove事件,几乎和手指移动的速度是一样的,UC和Chrome表现均是手指移动一段事件后,再从事件栈里面抛出触发,当然,Chrome触发的速度比UC好。还没有实际例子测试,不知是否会有影响,大家可以测试了给一下结果。
发现总结成博文好慢,先不写了,睡觉,接下来有时间将总结以下内容:
- 事件级联深入解析
- 300ms延迟的产生原理与解决方案
- 事件默认事件、事件冒泡在移动端的影响
- 触摸事件怎么玩?
- 触摸中的摇曳与HTML5中的摇曳栗子
- 触摸中无限滚动的栗子
- W3C中的Touch Events
- 未来的Pointer Events
没有评论:
发表评论