同步自个人博客,欢迎交流css
这篇文章在草稿箱里躺了好久,由于最近又遇到了相关问题,因而又整理了一下。请注意这里讲的不是 css
的 pointer-events
。jquery
从某个月黑风高的晚上开始,有人发现咱们的 web-app 在 Chrome 模拟器里开始出现报错,报错信息大概就是下面这样。git
VM1023:1 Uncaught TypeError: Cannot read property '0' of undefined
可是只有他的浏览器有问题,并且对功能毫无影响,本着在个人机器上不复现的精神(好吧,当时比较忙),这个问题的优先级排的不高,可是后面一段时间慢慢有人也出现相同的问题,因而我开始在乎这个问题了。github
根据调用栈很快定位到了代码,源码定位到以前一位同事写的组件代码,大概是这样的:web
dom.on('touchstart pointerdown', function (event) { /*部分业务代码*/ var touch = event.touches[0]; //报错的地方 /*部分业务代码*/ })
debug 发现是触发了 pointdown
事件,由于 event
没有 touches
这个字段,致使抛出异常。可是以前用的好好的呀,难道是浏览器的 API 变化了?并且我也没有了解过 pointerdown
事件,这个事件是用来处理什么的呢?因而我带着两个问题开启了搜索之旅:chrome
什么是 pointerdown
事件浏览器
为何忽然开始爆发错误app
查问题,最简单的问题就是搂一遍 W3C
的官方文档了。这里简单说下个人理解。dom
在 PC 时代,咱们经过鼠标与屏幕交互,这时候,咱们设计系统时只须要考虑鼠标事件就行了。可是现在,有不少新的设备,好比智能手机,平板电脑,他们包含了其余的输入方式,好比触摸,手写笔,官方也为这些输入形式都提供了新的事件。google
可是对于开发者来讲,这是件很麻烦的事,由于这意味着你须要为你的网页适配各类事件,好比你要根据用户的移动来画图,你须要兼容 PC 和手机,你的代码可能就会是下面这样
dom.addEventListener('mousemove', draw); dom.addEventListener('touchmove', draw);
若是须要兼容更多的输入设备呢?好比手写笔,这样的话代码就会很复杂。并且,为了兼容现有的基于鼠标事件的代码,不少浏览器都会为全部的输入类型触发鼠标事件(例如在 touchmove
时触发 mousemove
,我在 Chrome 试验了一下不会触发,可是由于没有设备,手写笔的状况没有试),这也会致使没法确认是否真的是鼠标触发的事件。
为了解决这一系列的问题,W3C 定义了一种新的输入形式,即 pointer
。任何由鼠标、触摸、手写笔或者其余输入设备在屏幕上触发的接触,都算是 pointer
事件。
它的 API 和鼠标事件很像,很是容易迁移。除了提供鼠标事件经常使用的属性,好比 clientX
,target
等等,还提供了一些用于其余输入设备的属性,好比压力,接触面,倾斜角度等等,这样开发者就能够利用 pointer
事件为全部的输入设备开发本身的功能了!
pointer 事件提供了一些特有的事件属性
pointerId:当前指针事件的惟一标识,主要是在多点触控时标识惟一的一个输入源
width:接触面的宽度
height:接触面的高度
pressure:接触的压力值,范围是0-1,对于不支持压力的硬件,好比鼠标,按压时该值必须为 0.5,不然为 0
tiltX,titltY:手写笔的角度
pointerType:事件类型,目前有 mouse
,pen
,touch
,若是是没法探测的指针类型,则该值为空字符串
isPrimary:用于标识是不是主指针,主要是在多点触控中生效,开发者也能够经过忽略非主指针的指针事件来实现单点触控。
如何肯定主指针:
鼠标输入:必定是主指针
触摸输入:若是 pointerdown
触发时没有其余激活的触摸事件,isPrimary
为 true
手写笔输入:与触摸事件相似,pointerdown
触发时没有其余激活的 pointer
事件
事件名称 | 做用 |
---|---|
pointerover |
与 mouseover 行为一致 |
pointerenter |
与 mouseenter 行为一致 |
pointerdown |
指针进入活动状态,好比触摸了屏幕,相似于 touchstart |
pointermove |
指针进行了移动 |
pointerup |
指针取消活动状态,好比手指离开了屏幕,相似于 touchend |
pointercancel |
相似于 touchcancel |
pointerout |
指针离开元素边缘或者离开屏幕,相似于 mouseout |
pointerleave |
相似于 mouseleave |
gotpointercapture |
元素捕获到指针事件时触发 |
lostpointercapture |
指针被释放时触发 |
能够看到,pointer
事件与已知的事件类型基本一致,可是有一点区别:在触摸屏上,咱们可能会滑动屏幕来触发页面滚动,缩放或者刷新,对于 touch
事件,这时会触发 touchmove
,可是对于 pointer
事件,当触发这些浏览器行为时,你却会接收到 pointercancel
事件以便于通知你浏览器已经接管了你的指针事件。
首先,pointer
事件的支持程度已经很不错了,你可使用 Pointer Events polyfill来进行兼容,也能够自行检测
if (window.PointerEvent) { // 支持 } else { // 不支持 }
这时候,对于本文一开始提到的问题就显而易见了,由于 point events
是没有 touches
这个属性的。那么咱们还有两个问题。
point events
?后来我看了下 zepto
的源码,在事件处理时是考虑到了 point event
的,同事以前写的代码大概是参考了 zepto
的事件系统。
很简答,Chrome 55 开始支持这个 API,Chrome 具体的支持信息能够参考官方日志,至于怎么检测浏览器支持,能够参考上面的内容
对于开发来讲,必定要钻进去,任何 bug 都是有缘由的
代码报错应该有相应的监控机制,让机器来帮咱们发现问题,而不是靠人工去干预
参考
https://www.w3.org/Submission...
https://developers.google.com...