深刻了解iPad上的MouseEvent

iPad上沒有鼠標,因此手指在觸發觸摸事件(TouchEvent)的時候,系統也會產生出模擬的鼠標事件(MouseEvent)。
    這對於普通網頁的瀏覽需求而言,基本能夠作到與PC端瀏覽器無明顯差別。可是若是你正在作一款與用戶有着強交互的WebAPP程序,好比一個html5小遊戲或者圖片處理工具什麼的,那麼依賴默認模擬恐怕不能知足產品的需求。
    一個一般的建議是:在iPad上(或者說各個移動終端上),你的WebAPP應該能處理好TouchEvent,而再也不依賴於MouseEvent。
    然而若是你的WebAPP須要同時面向PC和iPad兩種平臺的瀏覽器用戶,而迫於時間或者人力配備你無法分別提供兩種版本的時候。。。你也許有必要了解一下下面這些有關iPad上MouseEvent相關的細節,而後砍掉兩個平臺上有明顯差別的一些花哨特性,這樣才能作出一個較好地兼容兩個平臺的WebAPP。

     在閱讀下文前,我假設你已經熟悉PC瀏覽器上MouseEvent的運做,也對TouchEvent有了粗略的瞭解。若是你並不瞭解,那理解如下各個細節可能有困難。
  • safari只對可點擊(clickable)的HTML元素纔會產生MouseEvent。這在ADC文檔中也提到了。
    什麼叫可點擊,ADC文檔定義是隻要HTML元素響應mousemove、mousedown、mouseup、click四種MouseEvent中的一個就算是可點擊。若是你有個網頁菜單隻響應mouseover、mouseout,那可能不能工做,加個onclick="void(0)"就好了。但實際測試發現,只要響應任意一個MouseEvent就算可點擊了,估計safari已修正此問題。
    注意:下文全部關於「可點擊」「不可點擊」的描述都是針對是否響應MouseEvent而言,而不是指TouchEvent。
  • 與W3C規範建議的不一樣,iPad是在手指離開屏幕之後纔可能會產生MouseEvent。因此像手指單擊屏幕這種操做的實際事件序列一般是:touchstart->touchend->mousemove->mousedown->mouseup->click;而不是咱們指望的這樣的時序:touchstart->mousedown->touchend->mouseup->click。
  • 手指快速單擊屏幕觸發的MouseEvent並非緊跟在TouchEvent以後的,有一個時延。這是爲了等待可能的雙擊操做。iPad2 Safari的實測時延大約爲375ms。因此實際時序大約是這樣的:(手指按下)touchstart->(手指快速提起)touchend->(等待約375ms)mousemove->mousedown->mouseup->click。
    這對WebAPP的直接影響就是因爲從用戶操做完(手指提起)到onclick執行有375ms的延時,用戶總以爲你的軟件反應有點慢半拍。
    但若是單擊速度較慢,即手指按下到提起之間的時延超過大約120ms,touchend到其餘MouseEvent之間就再也不會有這個375ms的時延。由於系統認爲這已經不知足手指快速雙擊操做的斷定條件。
  • 手指快速雙擊屏幕操做不會觸發任何MouseEvent我是說「任何」,就是說不光不會觸發dblclick事件,連mousedown、mouseup、click等等全部MouseEvent都不會有。本操做默認的事件流是:touchstart->touchend->touchstart->touchend。若是頁面開發人員不作任何限制,瀏覽器默認行爲是嘗試縮放網頁。
  • 一次手指單擊操做不會同時產生mouseover和(mousedown、mouseup、click)兩組事件。若是一個響應mouseover事件的元素從渲染完畢或者上一次收到mouseout以後還沒有收到mouseover事件,則單擊觸發的事件流爲:touchstart->touchend->mouseover->mousemove;反之,單擊觸發的事件流爲:touchstart->touchend->mousemove->mousedown->mouseup->click。
    不響應mouseover事件的元素只會收到上述後一種事件流,這避免絕大多數連接須要手指點擊兩次才能跳轉頁面。
  • 一個HTML元素收到mouseover以後,只有在手指點擊另外一個可點擊的HTML元素時,纔會收到mouseout事件。由於沒有鼠標,因此不能像PC機上同樣在鼠標移入移除元素區域時觸發mouseover和mouseout事件,只能靠手指點擊來切換mouseover;又由於不可點擊的元素不會觸發任何MouseEvent,因此只有在另外一個HTML元素上觸發MouseEvent時前一個可點擊元素纔會收到mouseout事件。
  • 手指在屏幕上移動,不會觸發大量的mousemove事件。如第2點所說,只有在手指離開屏幕時,纔可能產生MouseEvent消息,因此你只可能收到一次mousemove事件,包括本次操做觸發的其餘全部MouseEvent,座標都是手指提起位置的座標。因此在PC瀏覽器上經過mousemove實現的邏輯,在iPad上須要經過TouchEvent來實現。
  • 實測發現,彷佛手指在屏幕上緩慢移動時,提起手指纔會觸發MouseEvent;若是手指快速移動,則提起手指不會觸發任何MouseEvent緣由不明。
  • 若是一個HTML元素響應TouchEvent,手指在該元素上按下並移動,即便手指移出該元素的區域,該元素仍然會收到touchmove事件,直到手指提起收到一個touchend結束。也就是說一個HTML元素一般總能收到一個完整的touchstart->(N個)touchmove->touchend事件序列,除非系統給它發出一個touchcancel事件。這跟PC瀏覽器上MouseEvent特性也不太相同。
  • 一旦在一次手指操做的事件序列touchstart->(0-N個)touchmove->touchend中的任何一個事件函數裏調用了event.preventDefault(),本次操做再也不產生任何MouseEvent因此不能指望在touchstart中調用preventDefault只阻止mousedown事件的產生。
  •     以上各個特性在iPad2/iOS4.3.3的safari上測試驗證過,對於其餘safari內核的瀏覽器(如QQ瀏覽器HD等)都是適用的。
        至於其餘非safari內核的瀏覽器,在MouseEvent的支持上基本都不如safari完整和合理。例如Opera Mini只有手指單擊屏幕時產生MouseEvent,而且不支持TouchEvent;UC瀏覽器雖然將mousedown移到了touchstart以後,可是手指移動後提起來卻不能產生mouseup事件。有興趣的能夠作進一步測試。Android用戶也能夠在Android平板電腦上作一些測試,若是能將測試結果分享給我,我將很是感謝。     【 附錄及參考文檔】

        1. 測試頁面連接:http://hokyhu.sinaapp.com/event_test.html
            你還能夠在這個頁面上體驗iPad強大的多點觸摸功能,試試看最多能檢測到幾個觸點。
        2. W3C關於TouchEvent的技術草案:https://dvcs.w3.org/hg/webevents/raw-file/tip/touchevents.html
            該草案主要定義了TouchEvent相關的技術細節,並少許涉及TouchEvent與MouseEvent之間的配合。
        3. ADC文檔:https://developer.apple.com/library/safari/documentation/AppleApplications/Reference/SafariWebContent/SafariWebContent.pdf
            文檔在「Handling Events」這一章描述了對MouseEvent的支持。html

    相關文章
    相關標籤/搜索