本文主要介绍 TouchEvent 相关的一些对象与属性如 Touch, TouchList, touhces, targetTouches 等,以及使用的注意点和误区。javascript
触摸事件有如下几种类型:touchstart
,touchmove
,touchend
这三种用的比较多,还有不经常使用的touchcancel
事件。固然 MDN上还介绍了touchenter
,touchleave
事件,具体适用的场景及兼容性如何还未作测试,感兴趣的可自行研究。java
js中不一样的事件类型,event
对象包含的属性也有所差别。咱们先了解几个TouchEvent
涉及的对象。chrome
提示:文中的demo都是在 chrome 模拟器,iPhone6s(iOS9.3.2) safari,iOS微信上运行,安卓的兼容性未作测试数组
Touch
对象表明一个触点,能够经过event.touches[0]获取,
每一个触点包含位置,大小,形状,压力大小,和目标 element属性。浏览器
{ screenX: 511, screenY: 400,//触点相对于屏幕左边沿的Y坐标 clientX: 244.37899780273438, clientY: 189.3820037841797,//相对于可视区域 pageX: 244.37, pageY: 189.37,//相对于HTML文档顶部,当页面有滚动的时候与clientX=Y 不等 force: 1,//压力大小,是从0.0(没有压力)到1.0(最大压力)的浮点数 identifier: 1036403715,//一次触摸动做的惟一标识符 radiusX: 37.565673828125, //可以包围用户和触摸平面的接触面的最小椭圆的水平轴(X轴)半径 radiusY: 37.565673828125, rotationAngle: 0,//它是这样一个角度值:由radiusX 和 radiusY 描述的正方向的椭圆,须要经过顺时针旋转这个角度值,才能最精确地覆盖住用户和触摸平面的接触面 target: {} // 这次触摸事件的目标element }
identifier
这个属性你们可能有疑惑,使用 Chrome 的模拟器发现屡次触摸动做,值始终不变。用真机测试则不会有问题(我这里用的safari链接mac调试)。每次触摸包括start,move,end这整个过程,标志符都不变。下一次触摸动做开始,标志符就会变化。微信
screenY
clientY
在 safari 中 screenY
与clientY
值是相等的,在iOS微信中两个数值不等,但单位应该也不同。ide
radiusX
radiusY
rotationAngle
测试过程当中safari及微信内置浏览器都不支持这些属性,chrome模拟器能够。测试
由Touch
对象构成的数组,经过event.touches
取到。一个Touch
对象表明一个触点,当有多个手指触摸屏幕时,TouchList
就会存储多个Touch
对象,前面说到的identifier
就用来区分每一个手指对应的Touch
对象。.net
TouchEvent
就是用来描述手指触摸屏幕的状态变化事件,除了通常DOM事件中event
对像具有的属性,还有一些特有的属性。设计
一个TouchList
对象,包含当前全部接触屏幕的触点的Touch
对象,不论 touchstart 事件从哪一个elment上触发。
也是一个TouchList
对象,包含了以下触点的 Touch 对象:touchstart从当前事件的目标element上触发
这里你们可能产生了疑惑,这两个对象到底有什么区别?尤为是咱们使用chrome模拟器中运行 demo,打印两个对象发现他们实际上是同样的。
这两个对象的区别能够类比event.target
与event.currentTarget
的区别,若是之前没留意,自行 js 高级程序设计。
咱们先看一个 demo2,来了解 touch 事件的特性。
在线编辑: http://jsrun.net/3XKKp
预览地址: http://jsrun.net/rtd/3XKKp
你们进行如下两个操做,观察控制台发现了什么?
操做一:一根手指触摸蓝色box
,并滑动,继续滑动出蓝色box
操做二:一根手指触摸非蓝色box
区域,而后慢慢滑动到蓝色box
你们会发现:操做一中即便滑出蓝色
box
,而touchmove
,touchend
事件会继续触发,touches
,targetTouches
存储着相同的 Touch 对象,touchmove事件的目标元素仍然是box。
操做二中相关的 touch 事件都不会触发。很神奇的是 touchmove 事件,明明在 box 上滑动,却不会触发 touchmove 事件。
咱们能够猜想,touch相关的事件是一个总体,一开始touchstart不可能被触发,则后续touch事件也不会被触发。固然你能够不监听 touchstart 事件,按照操做一 touchmove,touchend 仍是能够触发的。
再看下面这个demo2
在线编辑:http://jsrun.net/XXKKp
访问地址:http://jsrun.net/rtd/XXKKp
这里咱们对白色区域body
也添加了 touch 事件的监听,继续上述 demo1中的两个操做。
咱们能够发现:
操做一能够发现:touch 相关的事件能够冒泡,触发了
box
,body
的touch事件。操做二只能触发 body 的touch 事件,和demo1同理。
咱们能够观察下操做一的两个对象TouchEvent.targetTouches
,TouchEvent.touches
,不管是box
仍是body
触发的 touch 事件,他们的存储的 Touch对象都是相同的,并且 target 都是 box。
接下来进行操做三:
用两根手指,一根手指触摸蓝色
box
,另外一根触摸白色区域,而后滑动。
而后再次比较下targetTouches
和touches
,就能够发现他们的不一样。
也是一个 TouchList 对象,对于 touchstart 事件, 这个 TouchList 对象列出在这次事件中新增长的触点。对于 touchmove 事件,列出和上一次事件相比较,发生了变化的触点。对于 touchend ,列出离开触摸平面的触点(这些触点对应已经不接触触摸平面的手指)。
touchend
这里要特别注意,touches和targetTouches只存储接触屏幕的触点,要获取触点最后离开的状态要使用changedTouches。
以前也常常用touches[0]
来获取Touch 对象,若是知道了 touches,targetTouches,changedTouches 的不一样之处。在编写代码时能够更好的选择使用,程序也能够更严谨。
续篇想研究的问题:
touchmove的触发频率问题
如何断定用户是快速滑动(swipe事件)
如何实现Tap
一些使用总结或最佳实践
文中如理解有误,还请多多指出!