移动端触摸(touch)事件
移动端时代已经到来,作为前端开发的我们没有理由也不应该坐井观天,而是勇敢地跳出心里的那口井,去拥抱蔚蓝的天空。该来的总会来,我们要做的就是接受未知的挑战。正如你所看到的,这是一篇关于移动端触摸事件的文章,也就是我们平时在手机中用得最多的动作:touch。现在让我们开始 touch touch touch 吧!
Touch 事件
首先 touch 包含三类事件,它们分别是:touchstart、touchmove、touchend 。望文生义这种本能相信你应该会有,但在这里我还是有必需对这三个词进行一翻不必要的解释。
授课时间
touchstart:手指触摸到一个 DOM 元素时触发。
touchmove:手指在一个 DOM 元素上滑动时触发。
touchend:手指从一个 DOM 元素上移开时触发。
这三个事件又分别对应三个相同的触摸列表:
授课时间
touches:正在触摸屏幕的所有手指的一个列表。
targetTouches:正在触摸当前 DOM 元素上的手指的一个列表。
changedTouches:涉及当前事件的手指的一个列表。
Touch 属性
事件对应的三个列表虽然名字不一样,但是它们里面装的东西都是差不多的,包含了当前事件的一些相关信息,比如:一些坐标信息。
TouchList {0: Touch, length: 1}
length:1
0:Touch
clientX:65 // 触摸点在浏览器窗口中的横坐标
clientY:18 // 触摸点在浏览器窗口中的纵坐标
force:1 // 触摸点压力大小
identifier:0 // 触摸点唯一标识(ID)
pageX:65 // 触摸点在页面中的横坐标
pageY:18 // 触摸点在页面中的纵坐标
radiusX:11.5 // 触摸点椭圆的水平半径
radiusY:11.5 // 触摸点椭圆的垂直半径
rotationAngle:0 // 旋转角度
screenX:560 // 触摸点在屏幕中的横坐标
screenY:175 // 触摸点在屏幕中的纵坐标
target:div#touchLog 触摸目标
__proto__:Touch
__proto__:TouchList
上面就是一个 TouchList 列表。它对应的就是前面提到的三种事件(touchstart、touchmove、touchend)中的一种,在触发时生成的一个对象列表。列表里最有用的就是 Touch 对象了,Touch 对象里存放着对应事件的一些相关的信息,我们就是通过这种个事件里这些属性的有机结合来实现各种效果。
通过上面的 radiusX,radiusY,rotationAngle 这三个属性就可以计算出你的手指触摸手机屏幕时的一个接触面,只不过这个接触面是用一个近似的椭圆来表示,也就是说它不是一个真正意义上的接触面,而是一个大概的接触面。相信心细的朋友应该会看到 TouchList 对象里有一个 length 属性,并且它的值为 1 ,这说明当前只有一个手指触发了事件(比如:touchstart 事件),换句话说,此时你只有一个手指放到了手机屏幕上,这个手指对应的一些信息存放在 Touch 对象里。因为只有一个手指放在了屏幕上,所以这个 TouchList 里只有一个 Touch 对象,并且是第一个下标为 0 。TouchList 列表里还有一个 target 属性,这个应该很好理解,就是触摸的目标。
为了让你能更加立体地理解上面的这些属性,我专门从网上找了一段话来作为补充:
来自 mozilla
1.Touch.identifier:此 Touch 对象的唯一标识符。 一次触摸动作(我们指的是手指的触摸)在平面上移动的整个过程中,该标识符不变。 可以根据它来判断跟踪的是否是同一次触摸过程,此值为只读属性。
2.Touch.screenX:触点相对于屏幕左边沿的X坐标。只读属性。
3.Touch.screenY:触点相对于屏幕上边沿的Y坐标。只读属性。
4.Touch.clientX:触点相对于可见视区(visual viewport)左边沿的X坐标。不包括任何滚动偏移。只读属性。
5.Touch.clientY:触点相对于可见视区(visual viewport)上边沿的Y坐标。不包括任何滚动偏移。只读属性。
6.Touch.pageX:触点相对于HTML文档左边沿的X坐标。当存在水平滚动的偏移时,这个值包含了水平滚动的偏移。只读属性。
7.Touch.pageY:触点相对于HTML文档上边沿的Y坐标。当存在水平滚动的偏移时,这个值包含了垂直滚动的偏移。只读属性。
8.Touch.radiusX:能够包围用户和触摸平面的接触面的最小椭圆的水平轴(X轴)半径。这个值的单位和 screenX 相同。只读属性。
9.Touch.radiusY:能够包围用户和触摸平面的接触面的最小椭圆的垂直轴(Y轴)半径。这个值的单位和 screenY 相同。只读属性。
10.Touch.rotationAngle:它是这样一个角度值:由radiusX 和 radiusY描述的正方向的椭圆,需要通过顺时针旋转这个角度值,才能最精确地覆盖住用户和触摸平面的接触面。只读属性。
11.Touch.force:手指挤压触摸平面的压力大小,从0.0(没有压力)到1.0(最大压力)的浮点数。只读属性。
12.Touch.target:当这个触点最开始被跟踪时(在 touchstart 事件中),触点位于的HTML元素。哪怕在触点移动过程中,触点的位置已经离开了这个元素的有效交互区域,或者这个元素已经被从文档中移除。需要注意的是,如果这个元素在触摸过程中被移除,这个事件仍然会指向它,但是不会再冒泡这个事件到 window 或 document 对象。因此,如果有元素在触摸过程中可能被移除,最佳实践是将触摸事件的监听器绑定到这个元素本身,防止元素被移除后,无法再从它的上一级元素上侦测到从该元素冒泡的事件。只读属性。
Touch 初探
单指操作
为了更深入地理解 Touch 事件,我们现在来做一个简单的 DEMO 。
HTML 代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>移动端触摸(touch)事件</title>
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
<style>
#touchLog {
padding: 12px;
width: 100%;
box-sizing: border-box;
height: 300px;
}
</style>
</head>
<body>
<div id="touchLog">这里显示 touch 信息</div>
</body>
</html>
JavaScript 代码
<script>
var obj = document.getElementById("touchLog");
obj.addEventListener("touchstart", showMsg);
function showMsg(ev) {
console.log(ev.touches);
console.log(ev.targetTouches);
console.log(ev.changedTouches);
}
</script>
上面绑定的是 touchstart 事件,其它两个事件的用法一样,只是触发的时间点不一样而已。运行上面的代码会输出如下图的结果:

可能你会问:为什么它们的数据都是一样的,其实也很好理解,当你按下屏幕触发 touchstart 此时,然后执行了showMsg() 方法。那改成 touchmove 呢?不出意外的话,当你移动手指时第一组中的这三个 TouchList 也是一样的,为什么说第一组呢,因为 touchmove 是在你移动手指时才会触发的,所以当你不断移动手指时会多次触发自然而然地就会出现多组数据。但对于 touchend 就有点不一样了。你可以运行如下代码查看 touchend 与其它两个的区别:
<script>
var touchLog = document.getElementById("touchLog");
touchLog.addEventListener("touchstart", showMsgTouchstart);
function showMsgTouchstart(ev) {
console.log("---touchstart---");
console.log(ev.touches);
console.log(ev.targetTouches);
console.log(ev.changedTouches);
}
touchLog.addEventListener("touchmove", showMsgTouchmove);
function showMsgTouchmove(ev) {
console.log("---touchmove---");
console.log(ev.touches);
console.log(ev.targetTouches);
console.log(ev.changedTouches);
}
touchLog.addEventListener("touchend", showMsgTouchend);
function showMsgTouchend(ev) {
console.log("---touchend---");
console.log(ev.touches);
console.log(ev.targetTouches);
console.log(ev.changedTouches);
}
</script>
运行后你会发现 touchend 的 touches、targetTouches 里是没有 touch 对象的,length 值都为零,如下图:

这里我们还可以做别一个更有意思的测试,那就是触摸目标元素后,手指再滑出目标元素。上面三个事件对应的 touches、targetTouches 和 changedTouches 又会输出什么呢?还会是一样?
如果不出意外
1.touchstart 事件:touches、targetTouches 和 changedTouches 是一样的。
2.touchmove 事件:touches、targetTouches 和 changedTouches 是一样的(数据依然会有多组,原因上面也已经分析过了)。
3.touchend 事件:当你手指离开屏幕后,也就是 touchend 事件触发时,touches、targetTouches 的 TouchList 的 length 同样为0,也就是说没有 touch 对象。
所以使用 touchend 事件时需要注意只有 changedTouches 会存有触摸对象。但在 TouchList 对象中的 target 属性的值都为 div#touchLog,也就是说不管你触摸屏幕后手指是在目标元素上还是滑出目标元素,这个 target 属性的值还是 div#touchLog 。只要触摸了屏幕 force 的值都是 1 ,所以在这里感觉这个 force 还没有什么用武之地。
多指操作
我们先来看看下面的这一段代码,并且如果条件允许的话请用手机访问:http://yunkus.com/demo/mobile-touch-event/multi-finger-touchstart.html 查看touchstart 事件触发时的效果,代码如下:
<script>
var obj = document.getElementById("touchLog");
obj.addEventListener("touchstart", showMsg);
function showMsg(ev) {
obj.innerHTML = "";
var touchesStr = "";
var targetTouchesStr = "";
for (var i = 0; i < ev.touches.length; i++) {
touchesStr += "identifier:" + ev.touches[i].identifier + ",x 轴坐标:" + ev.touches[i].clientX + "<br>";
targetTouchesStr += "identifier:" + ev.targetTouches[i].identifier + ",x 轴坐标:" + ev.targetTouches[i]
.clientX + "<br>";
}
obj.innerHTML = "下面是 ev.touches 数据:<br>" + touchesStr +
"<br>下面是 ev.targetTouches 数据:<br>" + targetTouchesStr +
"<br>下面是 ev.changedTouches 数据:<br>" +
"identifier:" + ev.changedTouches[0].identifier + ",x 轴坐标:" + ev.changedTouches[0].clientX + "<br>";
}
</script>
访问 http://yunkus.com/demo/mobile-touch-event/multi-finger-touchmove.html 查看 touchmove 事件触发时的效果,touchmove 事件触发后 changedTouches 里的 touch 对象就不只一个了,而是跟其它两个 TouchList 列表一样。
访问 http://yunkus.com/demo/mobile-touch-event/multi-finger-touchend.html 查看 touchend 事件触发时的效果,touchmove 事件触发后就只有 changedTouches 里有 touch 且只有一个 touch 对象了,不管你同时在屏幕上放了多少根手指,这个 touch 对象对应的是你最后一次离开屏幕的那根手指。
上面的三个 demo 都会输出事件触发时的 touches 、targetTouches 和 changedTouches 里的 identifier 值,以及一个clientX 值。clientX 用于让你通过 x 的坐标来判断哪根手指对应哪个 identifier 的。对于 touchstart 事件而言,因为 changedTouches 里总是保存一个 touch 对象,所以没有遍历,而是直接通过下标访问。从上面我们可以得知有 touchstart 事件中 touches 、targetTouches 和 changedTouches 是有区别的:changedTouches 下只有一个 touch 对象,这个对象对应着触发事件最后一根发生改变(比如:最后触摸屏幕)的手指。这也就是为什么 changedTouches 里只有一个 touch 对象的原因,因为某一时刻下总是只有一个手指在变化。
但是也不能以偏盖全,因为 touchmove 事件中的 changedTouches 里就不只一个,而是跟 touches 和 targetTouches 同样有多个 touch 对象。
正如前面所说的 touchend 只有 changedTouches 列表里只有一个 touch 对象,这个对象对应着最后一根手指发生的改变(比如:最后离开屏幕)的手指。
通过研究单指操作跟多指操作,就可以让我们对 touch 事件了解得更加立体,到位。
默认事件
在移动端手指操作时会默认触发一些行为,比如:滚动,缩放。上面的例子是没有阻止触摸事件的默认行为的。所以当你测试上面 multi-finger-touchmove.html 这个例子时,你会发现有时候你会感到很无助,页面很容易发生缩放行为,甚至影响到测试效果。要想阻止触摸事件的默认行为也非常地简单只需要添加如下代码就可以了:
document.addEventListener("touchstart", function (ev) {
ev.preventDefault();
});
添加触摸事件的阻止默认行为的好处也不仅仅只有这一个。
1.在IOS 10 下设置 meta 禁止用户缩放是没有效果的,使用ev.preventDefault(); 就可以实现禁止用户缩放页面。
2.解决 IOS 10 下溢出隐藏(不起作用)的问题。
3.禁止系统默认的滚动条(如:横向滚动条)、以及橡皮筋效果。
4.禁止长按选中文字、选中图片、系统默认菜单。
5.解决点透问题。
虽然有那么多好处,需要注意的是此时也会带来一些问题,比如:input 不能获取焦点了。不过你可以通过单独的给 input 标签添加 touchstart 事件,并且阻止其冒泡就可以让 input 标签重生了。
var inputObj = document.getElementsByTagName("input")[0];
document.addEventListener("touchstart", function (ev) {
ev.preventDefault();
});
inputObj.addEventListener("touchstart", function (ev) {
ev.stopPropagation();
});
这里有一个 Demo,通过 touch 的相关事件实现的一个移动端焦点图切换效果 :http://yunkus.com/demo/mobile-touch-event/。
移动端触摸(touch)事件的更多相关文章
- 移动端 js touch事件
随着智能手机和平板电脑的普及, 越来越多的人用移动设备浏览网页,我们平时在pc浏览器上用的鼠标事件,比如:click, mouseover等, 已经无法满足移动设备触摸屏的特点,触摸时代的到来,离不开 ...
- 「移动端」touch事件,touchEvent对象
随着智能手机普及,有越来越多的手机网页和网页版游戏,手机触摸.移动.旋转等等,多种操作.一般电脑的人机交互靠的是鼠标,而手机用的就是触摸.区别有: PC 端一个电脑只能有一个鼠标,而移动端有多点触摸. ...
- 移动端的touch事件(一)
如果我们允许用户在页面上用类似桌面浏览器鼠标手势的方式来控制WEB APP,这个页面上肯定是有很多可点击区域的,如果用户触摸到了那些可点击区域怎么办呢?? 诸如智能手机和平板电脑一类的移动设备通常会有 ...
- 手机触摸touch事件
1.Touch事件简介 pc上的web页面鼠 标会产生onmousedown.onmouseup.onmouseout.onmouseover.onmousemove的事件,但是在移动终端如 ipho ...
- 浅谈移动端之touch事件--手指的滑动事件
今天台风‘海马’袭击深圳,全市停工.现分享一篇关于touch的文章,望指教! 原理: 当开始一个touchstart事件的时候,获取此刻手指的横坐标startX和纵坐标startY: 当触发touch ...
- 移动端html touch事件
诸如智能手机和平板电脑一类的移动设备通常会有一(capacitive touch-sensitivescreen),以捕捉用户的手指所做的交互.随着移动网络的发展,其能够支持越来越复杂的应用,web开 ...
- 移动端之touch事件--手指的滑动事件
转自[B5教程网]:http://www.bcty365.com/content-142-5243-1.html 总结:touchmove的最后坐标减去touchstart的起始坐标.X的结果如果正数 ...
- 《移动端浏览器Touch事件判断手指滑动方向方法》
$("body").on("touchstart", function(e) { e.preventDefault(); startX = e. ...
- Html5 移动端 触摸滑动事件
以下代码经过测试 没有问题 且可以循环滑动 <!DOCTYPE html><html xmlns="http://www.w3.org/1999/xhtml"& ...
- 对于移动端浏览器touch事件的研究总结(4)判断手指滑动方向
最近有一些微信的项目,虽然页面很简单,但配合手势后的效果却是很不错的.最基本的效果就是手指向上滑,页面配合css3出现一个展开效果,手指向下滑将展开的内容按原路径收起.其实就是一个简单的判断手指滑动方 ...
随机推荐
- Linux 查看对外开放端口
备忘命令: netstat -anpt | grep 514 # 查看 rsyslog tcp 端口是否开放 保持更新,转载请注明出处.
- 安全之路 —— 无DLL文件实现远程线程注入
简介 在之前的章节中,笔者曾介绍过有关于远程线程注入的知识,将后门.dll文件注入explorer.exe中实现绕过防火墙反弹后门.但一个.exe文件总要在注入时捎上一个.dll文件着 ...
- Mysql基础之 ALTER命令
ALTER命令: 作用:当我们修改数据库的列属性.列名称.表名等,要使用ALTER命令 教程: 1.首先是我们创建一个数据库以及一张表 mysql> create table exercise( ...
- February 6th, 2018 Week 6th Tuesday
To be is to be perceived. 存在即被感知. How to interpret this quote? Maybe it means that everything in you ...
- 寒假训练 A - A Knight's Journey 搜索
Background The knight is getting bored of seeing the same black and white squares again and again an ...
- WPFのImage控件souce引入的方法总结
1.后台代码相对路径添加(若为绝对路径,换UriKind的属性即可) BitmapImage testBitmapImage = new BitmapImage(new Uri(@"\bin ...
- P1802 5倍经验日(01背包问题,水题)
题目背景 现在乐斗有活动了!每打一个人可以获得5倍经验!absi2011却无奈的看着那一些比他等级高的好友,想着能否把他们干掉.干掉能拿不少经验的. 题目描述 现在absi2011拿出了x个迷你装药物 ...
- Yii2.0页面提示消息
适用情况:比如提交一个表单,提交完成之后在页面展示一条提示消息. 控制器里面这样写: 单条消息: \Yii::$app->getSession()->setFlash('error', ' ...
- hass连接设备
hass如何自动发现mqtt设备 https://www.hachina.io/docs/7230.html 玩家自定义 https://www.hachina.io/6572.html
- Qt 编程指南 4 按钮
1按钮类的控件 逐个解释一下各个用途:(1)按压按钮 QPushButton最基本的按钮,点击该按钮通常是通知程序进行一个操作,比如弹个窗.下一步.保存.退出等等,这是经常用到的,操作系统里的对话框里 ...