摘要:把事件統(tǒng)一起來(lái)處理用戶的輸入要用到事件。就這樣,提取了鼠標(biāo)觸摸屏觸控筆的共通之處,以方便開發(fā)跨設(shè)備的應(yīng)用。雖然是一個(gè)抽象,但它包含了鼠標(biāo)觸摸屏觸控筆的全部?jī)?nèi)容。手指與觸摸屏的屏幕接觸著,認(rèn)定為。
跨設(shè)備的問(wèn)題
平時(shí)我們?cè)陔娔X上訪問(wèn)的網(wǎng)頁(yè),大部分情況下是用鼠標(biāo)來(lái)控制的。比如說(shuō)鏈接跳轉(zhuǎn),就是鼠標(biāo)指針移動(dòng)到鏈接文字或圖片的位置,然后點(diǎn)擊一下。又比如說(shuō)滾動(dòng)屏幕,滑動(dòng)一下鼠標(biāo)滾輪就可以。
如果是供手機(jī)訪問(wèn)的網(wǎng)頁(yè)呢?這時(shí)候的控制就靠觸摸屏了。鏈接跳轉(zhuǎn)就是用手指點(diǎn)上去,滾動(dòng)屏幕則是手指按在屏幕上動(dòng)一動(dòng)。
因?yàn)槭遣煌脑O(shè)備(電腦、手機(jī)),所以盡管在瀏覽網(wǎng)頁(yè)時(shí)是類似的控制需求(鏈接跳轉(zhuǎn)、滾動(dòng)屏幕),但就會(huì)有不同的交互形式。這些交互形式,也是由設(shè)備所能提供的輸入方式(鼠標(biāo)、觸摸屏)決定的。
現(xiàn)在流行的響應(yīng)式設(shè)計(jì)的網(wǎng)頁(yè),追求的是只用一套代碼,也保證網(wǎng)頁(yè)在不同屏幕尺寸的設(shè)備上都具有較好的外觀。然而,這里的不同設(shè)備,可能不僅僅只是差在屏幕尺寸上,它們提供的輸入方式也可能不同。因此,想要開發(fā)出跨設(shè)備通用的網(wǎng)頁(yè),還要做一點(diǎn)別的事。
把事件統(tǒng)一起來(lái)處理用戶的輸入要用到事件。鼠標(biāo)的話,有我們熟悉的mouseover、click等,觸摸的話,也有touchstart、touchend等。不過(guò),這樣看就是要分別對(duì)兩種輸入做處理了,大概有點(diǎn)麻煩?如果邏輯也很近似的話,是不是還覺得有點(diǎn)不劃算?
如果能有一類事件,可以同時(shí)處理鼠標(biāo)、觸摸屏這些“雖不同但感覺有那么一點(diǎn)相似”的輸入就好了。對(duì)的,可以有,這就是本文要介紹的Pointer Events了。它已經(jīng)被W3C加入到推薦規(guī)范中。
抽象輸入:Pointer前面說(shuō)鼠標(biāo)、觸摸屏它們“雖不同但感覺有那么一點(diǎn)相似”,這其實(shí)是有章可循的。無(wú)論是鼠標(biāo)還是觸摸屏,其輸入都可以用屏幕上的一個(gè)或多個(gè)坐標(biāo)點(diǎn)來(lái)概括。Pointer就是描述這種坐標(biāo)點(diǎn)集合的抽象概念,代表此類輸入。除鼠標(biāo)和觸摸屏之外,還有一種常見的坐標(biāo)類型的輸入,是觸控筆,比如數(shù)位板或Surface搭配的筆。顯然,觸控筆也是坐標(biāo)類型,同樣可以用Pointer來(lái)表示。
就這樣,Pointer提取了鼠標(biāo)(mouse)、觸摸屏(touch)、觸控筆(pen)的共通之處,以方便開發(fā)跨設(shè)備的Web應(yīng)用。Pointer雖然是一個(gè)抽象,但它包含了鼠標(biāo)、觸摸屏、觸控筆的全部?jī)?nèi)容。比如,Pointer支持多點(diǎn)觸摸,而且還有壓力、傾斜度等信息。此外,Pointer還提供具體的輸入類型描述,也就是告訴你某個(gè)Pointer代表的到底是鼠標(biāo)、觸摸屏還是觸控筆,以幫助實(shí)現(xiàn)針對(duì)特定輸入的處理。
引入Pointer還有一個(gè)作用,就是如果同時(shí)有不同類型的輸入,可以更好地去實(shí)現(xiàn)符合JavaScript單線程風(fēng)格的響應(yīng)。因?yàn)檩斎胧录唤y(tǒng)一了,會(huì)比較有條理,不容易出錯(cuò)。
Pointer相關(guān)的一點(diǎn)術(shù)語(yǔ)了解Pointer之后,還需要注意一些描述Pointer的相關(guān)概念,它們算作術(shù)語(yǔ)。這里介紹兩個(gè)最主要的。
active pointer從名字上看,就是指處于激活狀態(tài)(active)的Pointer。實(shí)際上,這個(gè)詞是指“可以產(chǎn)生事件”的任意Pointer,這是什么意思呢?下面這些例子會(huì)比較容易理解:
和設(shè)備連接著的鼠標(biāo)一直是active。
手指與觸摸屏的屏幕接觸著,認(rèn)定為active。
位于數(shù)位板的響應(yīng)距離以內(nèi)的觸控筆,認(rèn)定為active(如果你用過(guò)數(shù)位板,你一定知道觸控筆只需要懸空在數(shù)位板上方一定距離內(nèi)就可以控制屏幕上的指針,并不需要觸碰到數(shù)位板)。
active buttons state這個(gè)可以看做在前面的基礎(chǔ)上,更進(jìn)一步狀態(tài)的Pointer。也同樣舉對(duì)應(yīng)的例子:
鼠標(biāo)有至少一個(gè)按鍵按下去了。
手指接觸到觸摸屏。
觸控筆觸碰到數(shù)位板(有物理接觸)。
你可能會(huì)發(fā)現(xiàn),手指觸摸的例子好像和前面是一樣的。這是因?yàn)?,就觸摸屏的設(shè)備而言,一般是沒(méi)有Hover(懸停)狀態(tài)一說(shuō)的。也就是說(shuō),對(duì)于手指觸摸輸入,一般的認(rèn)定是,并不能做到在“不產(chǎn)生按下效果”的情況下移動(dòng)Pointer。
Pointer事件列表和事件對(duì)象Pointer雖然是新的概念,但如前文所說(shuō),它包含了鼠標(biāo)、觸摸屏、觸控筆的全部?jī)?nèi)容。就具體的實(shí)現(xiàn)形式來(lái)說(shuō),它更像是現(xiàn)在常用的鼠標(biāo)事件的擴(kuò)展。比如,Pointer的pointerdown事件,正好對(duì)應(yīng)鼠標(biāo)的mousedown事件,它們非常近似。
原來(lái)的時(shí)候你這樣為DOM元素添加鼠標(biāo)事件:
elem.addEventListener("mousemove", mousemoveHandler, false);
現(xiàn)在換成Pointer以支持更多類型的輸入,你只需要這樣:
elem.addEventListener("pointermove", pointermoveHandler, false);
就一般的使用而言,需要用到的Pointer事件有pointerover、pointerenter、pointerdown、pointermove、pointerup、pointerout、pointerleave。它們?nèi)慷伎梢詫?duì)應(yīng)上我們熟悉的鼠標(biāo)事件。不過(guò),平時(shí)很常用的click并不在此列,但沒(méi)有關(guān)系,用pointerup來(lái)做就可以。
在事件處理函數(shù)里,會(huì)有一個(gè)event對(duì)象,包含事件的相關(guān)信息。Pointer的event對(duì)象實(shí)際上繼承了鼠標(biāo)的event對(duì)象,然后新增了一部分只讀屬性。其中比較重要的幾個(gè):
pointerId這是一個(gè)數(shù)字,用于分別標(biāo)識(shí)當(dāng)前處于active狀態(tài)的各個(gè)Pointer。在任何Pointer的事件處理函數(shù)內(nèi),都可以依靠這個(gè)數(shù)字標(biāo)記來(lái)確認(rèn)處理的是否是同一個(gè)Pointer。
pointerType字符串,就是前文所說(shuō)的告訴你這個(gè)Pointer是鼠標(biāo)(mouse)、觸摸屏(touch)還是觸控筆(pen)。如果是除這些之外的無(wú)法識(shí)別的輸入,這個(gè)屬性會(huì)是空字符串。
isPrimary邏輯值,表示這個(gè)Pointer是否是“主要的”(primary)。請(qǐng)看下文。
Primary Pointer前文提到過(guò),Pointer支持多點(diǎn)。所以,這個(gè)概念可以幫助確認(rèn)哪一個(gè)是首要的點(diǎn)。具體來(lái)說(shuō),鼠標(biāo)是只能一個(gè)的,所以代表鼠標(biāo)的那個(gè)Pointer,一定是primary。而對(duì)于觸摸屏或觸控筆,在多點(diǎn)輸入的情況下,只有“最初”的那一個(gè)算作primary。這里“最初”指的是,在pointerdown事件發(fā)生的時(shí)候,沒(méi)有其他同類型(觸摸對(duì)觸摸,筆對(duì)筆)的active狀態(tài)的Pointer存在。
因?yàn)橐环N類型就可以有一個(gè)Primary Pointer,所以可以有多個(gè)Primary Pointer。比如同時(shí)有手指觸摸和鼠標(biāo)指針,它們的Pointer都會(huì)被認(rèn)定為primary。
一般來(lái)說(shuō),應(yīng)用同一時(shí)間只響應(yīng)一個(gè)輸入點(diǎn)的情況比較多,因此可以利用Pointer事件對(duì)象的isPrimary來(lái)忽略掉那些額外的輸入點(diǎn)。
相關(guān)的css屬性:touch-action在支持手指觸摸的設(shè)備中,一次手指觸摸中的動(dòng)作,是有默認(rèn)行為(default behavior)的。比如,縮放(zooming)和平移(panning,和滾動(dòng)屏幕scrolling同義)。這些默認(rèn)行為,和完整的Pointer事件是不相容的。根據(jù)手指的動(dòng)作,如果被判定為觸摸的默認(rèn)行為,就不會(huì)再按照預(yù)想的那樣觸發(fā)Pointer的事件。因此,你可能想要在某些范圍內(nèi),確保不觸發(fā)觸摸的某些默認(rèn)行為,保證Pointer事件按照預(yù)想進(jìn)行。
css屬性touch-action一般用在塊元素上,它的取值分別有:
auto默認(rèn)值。允許任何設(shè)備支持的默認(rèn)行為。
none不會(huì)觸發(fā)任何默認(rèn)行為。
pan-x只允許“水平方向的平移”這一默認(rèn)行為。
pan-y只允許“垂直方向的平移”這一默認(rèn)行為。
manipulation只允許“平移”和“縮放”這兩種默認(rèn)行為。設(shè)備支持的其他默認(rèn)行為(也就是auto里額外的部分)不會(huì)觸發(fā)。
在手機(jī)這樣的觸摸屏設(shè)備里,通過(guò)手指平移來(lái)滾動(dòng)瀏覽網(wǎng)頁(yè)是很普遍的,所以應(yīng)謹(jǐn)慎地用這個(gè)屬性來(lái)取消部分默認(rèn)行為。
瀏覽器兼容性根據(jù)caniuse上的結(jié)果,在默認(rèn)情況下,除了IE11及Windows 10的Edge,其他所有瀏覽器都不支持。
???那怎么投入實(shí)用?
Pointer Events Polyfill類似很多其他新的技術(shù)規(guī)范,Pointer Events也有Polyfill,就叫做Pointer Events Polyfill,由jQuery團(tuán)隊(duì)開發(fā),簡(jiǎn)稱PEP。
這個(gè)Polyfill并不能實(shí)現(xiàn)規(guī)范的全部?jī)?nèi)容,而是有些偏差,因此需要注意幾個(gè)地方:
一是touch-action需要用html屬性形式使用。例如:
二是只有設(shè)置了touch-action屬性的元素內(nèi)部,才能觸發(fā)Pointer Events。也就是需要偵聽Pointer事件的區(qū)域,一定要選至少一個(gè)元素加上touch-action。
這樣設(shè)置好之后,就可以像使用鼠標(biāo)事件那樣來(lái)使用Pointer Events了,比如結(jié)合jQuery的使用示例:
$("#canvas").on("pointermove", function(event) { draw(event); });
加上這個(gè)Polyfill后,將支持IE10+及其他各類瀏覽器(包括手機(jī)上的)。
和css屬性pointer-events的關(guān)系并,沒(méi),有,什,么,關(guān),系,請(qǐng)明確地區(qū)分它們。
結(jié)語(yǔ)像鏈接跳轉(zhuǎn)、滾動(dòng)屏幕這樣的簡(jiǎn)單響應(yīng),電腦和手機(jī)上的瀏覽器默認(rèn)就已經(jīng)做好了處理,并不需要我們做什么。但要做跨設(shè)備通用的、更復(fù)雜的Web應(yīng)用,Pointer Events可以很大程度上簡(jiǎn)化對(duì)多種輸入方式的處理。
我是因?yàn)橐淮螒?yīng)用開發(fā)中不能容忍click事件在觸摸設(shè)備上的延遲,這才找到了Pointer Events。應(yīng)該說(shuō),很贊同Pointer Events的這種化繁為簡(jiǎn)的整合理念,但從它目前的瀏覽器兼容性來(lái)看,它還有很遠(yuǎn)的路要走。不過(guò),隨著未來(lái)更多輸入設(shè)備的發(fā)展,它有可能會(huì)以另外的形式再次入場(chǎng)。
(重新編輯自我的博客,原文地址:http://acgtofe.com/posts/2015/11/pointer-events-for-cross-platform)
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/78238.html
摘要:把事件統(tǒng)一起來(lái)處理用戶的輸入要用到事件。就這樣,提取了鼠標(biāo)觸摸屏觸控筆的共通之處,以方便開發(fā)跨設(shè)備的應(yīng)用。雖然是一個(gè)抽象,但它包含了鼠標(biāo)觸摸屏觸控筆的全部?jī)?nèi)容。手指與觸摸屏的屏幕接觸著,認(rèn)定為。 跨設(shè)備的問(wèn)題 平時(shí)我們?cè)陔娔X上訪問(wèn)的網(wǎng)頁(yè),大部分情況下是用鼠標(biāo)來(lái)控制的。比如說(shuō)鏈接跳轉(zhuǎn),就是鼠標(biāo)指針移動(dòng)到鏈接文字或圖片的位置,然后點(diǎn)擊一下。又比如說(shuō)滾動(dòng)屏幕,滑動(dòng)一下鼠標(biāo)滾輪就可以。 如果是...
推薦 1. JavaScript 在嵌入式設(shè)備與物聯(lián)網(wǎng)中的應(yīng)用現(xiàn)狀 https://auth0.com/blog/javasc... 隨著近年來(lái) Web 的發(fā)展與 JavaScript 的崛起,JavaScript 被應(yīng)用到了許多原本不曾想象到的場(chǎng)景中,從服務(wù)端、工作站、數(shù)據(jù)庫(kù)、桌面環(huán)境到物聯(lián)網(wǎng)設(shè)備中,都可以見到 JavaScript 的身影。而本文則概括了 JavaScript 在不同的嵌入式微...
推薦 1. JavaScript 在嵌入式設(shè)備與物聯(lián)網(wǎng)中的應(yīng)用現(xiàn)狀 https://auth0.com/blog/javasc... 隨著近年來(lái) Web 的發(fā)展與 JavaScript 的崛起,JavaScript 被應(yīng)用到了許多原本不曾想象到的場(chǎng)景中,從服務(wù)端、工作站、數(shù)據(jù)庫(kù)、桌面環(huán)境到物聯(lián)網(wǎng)設(shè)備中,都可以見到 JavaScript 的身影。而本文則概括了 JavaScript 在不同的嵌入式微...
推薦 1. JavaScript 在嵌入式設(shè)備與物聯(lián)網(wǎng)中的應(yīng)用現(xiàn)狀 https://auth0.com/blog/javasc... 隨著近年來(lái) Web 的發(fā)展與 JavaScript 的崛起,JavaScript 被應(yīng)用到了許多原本不曾想象到的場(chǎng)景中,從服務(wù)端、工作站、數(shù)據(jù)庫(kù)、桌面環(huán)境到物聯(lián)網(wǎng)設(shè)備中,都可以見到 JavaScript 的身影。而本文則概括了 JavaScript 在不同的嵌入式微...
閱讀 1063·2021-11-24 09:39
閱讀 3602·2021-11-22 13:54
閱讀 2558·2021-10-11 10:59
閱讀 796·2021-09-02 15:40
閱讀 1036·2019-08-30 15:55
閱讀 1053·2019-08-30 13:57
閱讀 2314·2019-08-30 13:17
閱讀 3034·2019-08-29 18:32