Web基礎體驗改進一:滑動閂鎖(Scroll Latch)

1. 背景

chromium中網頁的可滑動子節點滑動到邊緣後,再次滑動會帶動父節點滑動。在一些場景中需要將發生在子節點的滑動事件鎖住,即使滑動到邊緣也不帶動父節點的滑動。例如以下頁面中間的歌詞部分滑動到邊緣後,再次滑動不希望將未消耗的滑動量傳遞到父節點,目前是通過js來實現,如果能夠在chromium中直接實現滑動持久閂鎖的效果,可以不必使用js。

Web基礎體驗改進一:滑動閂鎖(Scroll Latch)

2. scroll手勢Begin處理流程

Web基礎體驗改進一:滑動閂鎖(Scroll Latch)

Web基礎體驗改進一:滑動閂鎖(Scroll Latch)

在InputHandlerProxy::HandleInputEvent中kGestureScrollBegin對應於scroll手勢的起始處理,kGestureScrollUpdate對應於scroll手勢的進行處理,kGestureScrollEnd對應於scroll手勢的結束處理。

Web基礎體驗改進一:滑動閂鎖(Scroll Latch)

在起始處理過程中,最終會調用LayerTreeHostImpl::DistributeScrollDelta進行滑動鏈(current_scroll_chain)的確認,scroll_chain中放入可以消耗滑動量的scroll node,子節點在鏈表尾,父節點在鏈表頭。Scroll node 與 active layer對應關係為每個layer都會指定4顆property tree的一個節點。

Web基礎體驗改進一:滑動閂鎖(Scroll Latch)

關於4顆屬性樹的相關信息在src/cc/trees/property_tree.h裡

Web基礎體驗改進一:滑動閂鎖(Scroll Latch)

3. scroll chain

Web基礎體驗改進一:滑動閂鎖(Scroll Latch)

其中viewport_scroll_node對應於網頁的滑動節點,當該節點被放入滑動鏈時,有可能會將滑動量傳遞到網頁本身,即網頁子元素的滑動有可能會傳遞到網頁本身,由於chromium做了scroll latch,滑動嵌套時不會將滑動傳遞到parent節點,但是二次滑動時就會直接滑動parent節點(子節點無法消耗滑動量,沒有進入scroll chain)。

4. scroll latch

要想實現可滑動子元素在滑動到邊緣後後續滑動都不帶動parent節點,可以在scroll chain中進行更改。當滑動發生在可滑動子元素上時,通過CanConsumeDelta判斷該節點是否能夠消耗滑動量,如果可以則進入滑動鏈。而當可滑動子節點以及滑動到邊緣時,此函數返回false則滑動鏈跳過該子節點,直接加入父節點。所以可以在此進行判斷等相關處理,若存在不可消耗滑動的子節點,父節點不進入滑動鏈,此處細節部分是對滑動方向的一致性判斷,防止橫向滑動鎖住垂直滑動。

Scroll node有水平和垂直滑動的屬性,但是從測試結果來看,只要area是可滑動的兩者都為true,此性質無法使用。可以從如何判斷滑動是否能夠消耗來進行處理,詳細見CanConsumeDelta函數。

Web基礎體驗改進一:滑動閂鎖(Scroll Latch)

修改DistributeScrollDelta函數,首先獲取當前滑動的手勢方向並創建是否需要持久閂鎖的標誌。

Web基礎體驗改進一:滑動閂鎖(Scroll Latch)

根據是否需要持久閂鎖,判斷頁面節點是否能進入scroll chain。

Web基礎體驗改進一:滑動閂鎖(Scroll Latch)

判斷當前scroll node的可滑動方向是否與手勢的滑動方向完全一致,如果完全一致且不能消耗滑動量,設置持久閂鎖標誌。

Web基礎體驗改進一:滑動閂鎖(Scroll Latch)

(ps:以上實現是針對上級滑動節點為整個網頁節點的情形,如果是多層滑動嵌套,可以直接在child_scroll_should_latch=true時break即可)。

所以進行修改後滑動鏈將為空,此時LayerTreeHostImpl::ScrollBeginImpl處理為返回scroll_ignore信息。

Web基礎體驗改進一:滑動閂鎖(Scroll Latch)

到了InputHandlerProxy::HandleGestureScrollBegin函數中後,render端會丟棄該滑動事件並且通知browser端,最終該滑動事件沒有產生效果,即沒有帶動父節點滑動,子節點滑動在邊緣被持久閂鎖。

Web基礎體驗改進一:滑動閂鎖(Scroll Latch)

5. 調試

【修改前】

首次滑動到邊緣時,滑動的子節點4和滑動的父節點3都進入scroll chain。

Web基礎體驗改進一:滑動閂鎖(Scroll Latch)

在邊緣處再次滑動時,滑動的子節點已經不能消耗滑動量,所以只有父節點3進入scroll chain,從而將滑動了整個網頁。

Web基礎體驗改進一:滑動閂鎖(Scroll Latch)

【修改後】

在邊緣處再次滑動時,發生持久閂鎖

Web基礎體驗改進一:滑動閂鎖(Scroll Latch)


分享到:


相關文章: