深入瞭解iPad上的MouseEvent

深入瞭解iPad上的MouseEvent

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

 

    在閱讀下文前,我假設你已經熟悉PC瀏覽器上MouseEvent的運作,也對TouchEvent有了粗略的瞭解。如果你並不瞭解,那理解以下各個細節可能有困難。

 

  1. safari只對可點擊(clickable)的HTML元素纔會產生MouseEvent。這在ADC文檔中也提到了。
    什麼叫可點擊,ADC文檔定義是隻要HTML元素響應mousemove、mousedown、mouseup、click四種MouseEvent中的一個就算是可點擊。如果你有個網頁菜單隻響應mouseover、mouseout,那可能不能工作,加個οnclick="void(0)"就行了。但實際測試發現,只要響應任意一個MouseEvent就算可點擊了,估計safari已修正此問題。
    注意:下文所有關於“可點擊”“不可點擊”的描述都是針對是否響應MouseEvent而言,而不是指TouchEvent。
  2. 與W3C規範建議的不同,iPad是在手指離開屏幕以後纔可能會產生MouseEvent。所以像手指單擊屏幕這種操作的實際事件序列通常是:touchstart->touchend->mousemove->mousedown->mouseup->click;而不是我們期望的這樣的時序:touchstart->mousedown->touchend->mouseup->click。
  3. 手指快速單擊屏幕觸發的MouseEvent並不是緊跟在TouchEvent之後的,有一個時延。這是爲了等待可能的雙擊操作。iPad2 Safari的實測時延大約爲375ms。所以實際時序大約是這樣的:(手指按下)touchstart->(手指快速提起)touchend->(等待約375ms)mousemove->mousedown->mouseup->click。
    這對WebAPP的直接影響就是由於從用戶操作完(手指提起)到onclick執行有375ms的延時,用戶總覺得你的軟件反應有點慢半拍。
    但如果單擊速度較慢,即手指按下到提起之間的時延超過大約120ms,touchend到其他MouseEvent之間就不再會有這個375ms的時延。因爲系統認爲這已經不滿足手指快速雙擊操作的判定條件。
  4. 手指快速雙擊屏幕操作不會觸發任何MouseEvent。我是說“任何”,就是說不光不會觸發dblclick事件,連mousedown、mouseup、click等等所有MouseEvent都不會有。本操作默認的事件流是:touchstart->touchend->touchstart->touchend。如果頁面開發人員不做任何限制,瀏覽器默認行爲是嘗試縮放網頁。
  5. 一次手指單擊操作不會同時產生mouseover和(mousedown、mouseup、click)兩組事件。如果一個響應mouseover事件的元素從渲染完畢或者上一次收到mouseout之後尚未收到mouseover事件,則單擊觸發的事件流爲:touchstart->touchend->mouseover->mousemove;反之,單擊觸發的事件流爲:touchstart->touchend->mousemove->mousedown->mouseup->click。
    不響應mouseover事件的元素只會收到上述後一種事件流,這避免絕大多數鏈接需要手指點擊兩次才能跳轉頁面。
  6. 一個HTML元素收到mouseover之後,只有在手指點擊另一個可點擊的HTML元素時,纔會收到mouseout事件。因爲沒有鼠標,所以不能像PC機上一樣在鼠標移入移除元素區域時觸發mouseover和mouseout事件,只能靠手指點擊來切換mouseover;又因爲不可點擊的元素不會觸發任何MouseEvent,所以只有在另一個HTML元素上觸發MouseEvent時前一個可點擊元素纔會收到mouseout事件。
  7. 手指在屏幕上移動,不會觸發大量的mousemove事件。如第2點所說,只有在手指離開屏幕時,纔可能產生MouseEvent消息,所以你只可能收到一次mousemove事件,包括本次操作觸發的其他所有MouseEvent,座標都是手指提起位置的座標。所以在PC瀏覽器上通過mousemove實現的邏輯,在iPad上需要通過TouchEvent來實現。
  8. 實測發現,似乎手指在屏幕上緩慢移動時,提起手指纔會觸發MouseEvent;如果手指快速移動,則提起手指不會觸發任何MouseEvent。原因不明。
  9. 如果一個HTML元素響應TouchEvent,手指在該元素上按下並移動,即使手指移出該元素的區域,該元素仍然會收到touchmove事件,直到手指提起收到一個touchend結束。也就是說一個HTML元素通常總能收到一個完整的touchstart->(N個)touchmove->touchend事件序列,除非系統給它發出一個touchcancel事件。這跟PC瀏覽器上MouseEvent特性也不太相同。
  10. 一旦在一次手指操作的事件序列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的支持。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章