同步自個人博客,歡迎交流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...