平时咱们在电脑上访问的网页,大部分状况下是用鼠标来控制的。好比说连接跳转,就是鼠标指针移动到连接文字或图片的位置,而后点击一下。又好比说滚动屏幕,滑动一下鼠标滚轮就能够。css
若是是供手机访问的网页呢?这时候的控制就靠触摸屏了。连接跳转就是用手指点上去,滚动屏幕则是手指按在屏幕上动一动。html
由于是不一样的设备(电脑、手机),因此尽管在浏览网页时是相似的控制需求(连接跳转、滚动屏幕),但就会有不一样的交互形式。这些交互形式,也是由设备所能提供的输入方式(鼠标、触摸屏)决定的。jquery
如今流行的响应式设计的网页,追求的是只用一套代码,也保证网页在不一样屏幕尺寸的设备上都具备较好的外观。然而,这里的不一样设备,可能不只仅只是差在屏幕尺寸上,它们提供的输入方式也可能不一样。所以,想要开发出跨设备通用的网页,还要作一点别的事。git
处理用户的输入要用到事件。鼠标的话,有咱们熟悉的mouseover
、click
等,触摸的话,也有touchstart
、touchend
等。不过,这样看就是要分别对两种输入作处理了,大概有点麻烦?若是逻辑也很近似的话,是否是还以为有点不划算?github
若是能有一类事件,能够同时处理鼠标、触摸屏这些“虽不一样但感受有那么一点类似”的输入就行了。对的,能够有,这就是本文要介绍的Pointer Events了。它已经被W3C加入到推荐规范中。canvas
前面说鼠标、触摸屏它们“虽不一样但感受有那么一点类似”,这实际上是有章可循的。不管是鼠标仍是触摸屏,其输入均可以用屏幕上的一个或多个坐标点来归纳。Pointer就是描述这种坐标点集合的抽象概念,表明此类输入。除鼠标和触摸屏以外,还有一种常见的坐标类型的输入,是触控笔,好比数位板或Surface搭配的笔。显然,触控笔也是坐标类型,一样能够用Pointer来表示。浏览器
就这样,Pointer提取了鼠标(mouse)、触摸屏(touch)、触控笔(pen)的共通之处,以方便开发跨设备的Web应用。Pointer虽然是一个抽象,但它包含了鼠标、触摸屏、触控笔的所有内容。好比,Pointer支持多点触摸,并且还有压力、倾斜度等信息。此外,Pointer还提供具体的输入类型描述,也就是告诉你某个Pointer表明的究竟是鼠标、触摸屏仍是触控笔,以帮助实现针对特定输入的处理。函数
引入Pointer还有一个做用,就是若是同时有不一样类型的输入,能够更好地去实现符合JavaScript单线程风格的响应。由于输入事件被统一了,会比较有条理,不容易出错。post
了解Pointer以后,还须要注意一些描述Pointer的相关概念,它们算做术语。这里介绍两个最主要的。spa
从名字上看,就是指处于激活状态(active)的Pointer。实际上,这个词是指“能够产生事件”的任意Pointer,这是什么意思呢?下面这些例子会比较容易理解:
和设备链接着的鼠标一直是active。
手指与触摸屏的屏幕接触着,认定为active。
位于数位板的响应距离之内的触控笔,认定为active(若是你用过数位板,你必定知道触控笔只须要悬空在数位板上方必定距离内就能够控制屏幕上的指针,并不须要触碰到数位板)。
这个能够看作在前面的基础上,更进一步状态的Pointer。也一样举对应的例子:
鼠标有至少一个按键按下去了。
手指接触到触摸屏。
触控笔触碰到数位板(有物理接触)。
你可能会发现,手指触摸的例子好像和前面是同样的。这是由于,就触摸屏的设备而言,通常是没有Hover(悬停)状态一说的。也就是说,对于手指触摸输入,通常的认定是,并不能作到在“不产生按下效果”的状况下移动Pointer。
Pointer虽然是新的概念,但如前文所说,它包含了鼠标、触摸屏、触控笔的所有内容。就具体的实现形式来讲,它更像是如今经常使用的鼠标事件的扩展。好比,Pointer的pointerdown
事件,正好对应鼠标的mousedown
事件,它们很是近似。
原来的时候你这样为DOM元素添加鼠标事件:
elem.addEventListener("mousemove", mousemoveHandler, false);
如今换成Pointer以支持更多类型的输入,你只须要这样:
elem.addEventListener("pointermove", pointermoveHandler, false);
就通常的使用而言,须要用到的Pointer事件有pointerover
、pointerenter
、pointerdown
、pointermove
、pointerup
、pointerout
、pointerleave
。它们所有均可以对应上咱们熟悉的鼠标事件。不过,平时很经常使用的click
并不在此列,但没有关系,用pointerup
来作就能够。
在事件处理函数里,会有一个event
对象,包含事件的相关信息。Pointer的event
对象实际上继承了鼠标的event
对象,而后新增了一部分只读属性。其中比较重要的几个:
这是一个数字,用于分别标识当前处于active状态的各个Pointer。在任何Pointer的事件处理函数内,均可以依靠这个数字标记来确认处理的是不是同一个Pointer。
字符串,就是前文所说的告诉你这个Pointer是鼠标(mouse)、触摸屏(touch)仍是触控笔(pen)。若是是除这些以外的没法识别的输入,这个属性会是空字符串。
逻辑值,表示这个Pointer是不是“主要的”(primary)。请看下文。
前文提到过,Pointer支持多点。因此,这个概念能够帮助确认哪个是首要的点。具体来讲,鼠标是只能一个的,因此表明鼠标的那个Pointer,必定是primary。而对于触摸屏或触控笔,在多点输入的状况下,只有“最初”的那一个算做primary。这里“最初”指的是,在pointerdown
事件发生的时候,没有其余同类型(触摸对触摸,笔对笔)的active状态的Pointer存在。
由于一种类型就能够有一个Primary Pointer,因此能够有多个Primary Pointer。好比同时有手指触摸和鼠标指针,它们的Pointer都会被认定为primary。
通常来讲,应用同一时间只响应一个输入点的状况比较多,所以能够利用Pointer事件对象的isPrimary
来忽略掉那些额外的输入点。
在支持手指触摸的设备中,一次手指触摸中的动做,是有默认行为(default behavior)的。好比,缩放(zooming)和平移(panning,和滚动屏幕scrolling同义)。这些默认行为,和完整的Pointer事件是不相容的。根据手指的动做,若是被断定为触摸的默认行为,就不会再按照预想的那样触发Pointer的事件。所以,你可能想要在某些范围内,确保不触发触摸的某些默认行为,保证Pointer事件按照预想进行。
css属性touch-action
通常用在块元素上,它的取值分别有:
默认值。容许任何设备支持的默认行为。
不会触发任何默认行为。
只容许“水平方向的平移”这一默认行为。
只容许“垂直方向的平移”这一默认行为。
只容许“平移”和“缩放”这两种默认行为。设备支持的其余默认行为(也就是auto
里额外的部分)不会触发。
在手机这样的触摸屏设备里,经过手指平移来滚动浏览网页是很广泛的,因此应谨慎地用这个属性来取消部分默认行为。
根据caniuse上的结果,在默认状况下,除了IE11及Windows 10的Edge,其余全部浏览器都不支持。
啊?那怎么投入实用?
相似不少其余新的技术规范,Pointer Events也有Polyfill,就叫作Pointer Events Polyfill,由jQuery团队开发,简称PEP。
这个Polyfill并不能实现规范的所有内容,而是有些误差,所以须要注意几个地方:
一是touch-action
须要用html属性形式使用。例如:
<canvas width="800" height="600" touch-action="none"></canvas>
二是只有设置了touch-action
属性的元素内部,才能触发Pointer Events。也就是须要侦听Pointer事件的区域,必定要选至少一个元素加上touch-action
。
这样设置好以后,就能够像使用鼠标事件那样来使用Pointer Events了,好比结合jQuery的使用示例:
$("#canvas").on("pointermove", function(event) { draw(event); });
加上这个Polyfill后,将支持IE10+及其余各种浏览器(包括手机上的)。
并,没,有,什,么,关,系,请明确地区分它们。
像连接跳转、滚动屏幕这样的简单响应,电脑和手机上的浏览器默认就已经作好了处理,并不须要咱们作什么。但要作跨设备通用的、更复杂的Web应用,Pointer Events能够很大程度上简化对多种输入方式的处理。
我是由于一次应用开发中不能容忍click
事件在触摸设备上的延迟,这才找到了Pointer Events。应该说,很赞同Pointer Events的这种化繁为简的整合理念,但从它目前的浏览器兼容性来看,它还有很远的路要走。不过,随着将来更多输入设备的发展,它有可能会以另外的形式再次入场。
(从新编辑自个人博客,原文地址:http://acgtofe.com/posts/2015/11/pointer-events-for-cross-platform)