Web基礎體驗改進五:scroll-snap
來自專欄 Chromium代碼學習12 人贊了文章
scroll-snap是一個很有用的CSS屬性,功能是滑動結束後,自動對齊內部元素(area)。抖音 app 中,上下滑動視頻的對齊元素的同時,一次只能滑過一個視頻,這樣的需求 scroll snap 暫時並不能實現。因此我們提出新的屬性 scroll-snap-element 來支持這樣的交互場景。
value:
- momentum: 和 scroll-snap 原來的滑動邏輯一致,可能會滑動多個內部元素
- next: 一次滑動(包括 snap_fling )只能滑過一個內部元素
以抖音首頁為例看一下效果對比:
scroll-snap-element:momentum https://www.zhihu.com/video/1020726591374163968 scroll-snap-element:next https://www.zhihu.com/video/1020726830197796864
在 CSS Scroll Snap 的 Editor『s Draft 中存在屬性 scroll-snap-stop,具體定義有出入但功能類似,由於被判斷為是 at risk,所以沒有被實現。
原生snap_fling動作的分析
fling慣性滑動,是用戶結束滑動操作仍有未消耗動量的 gesture_event,慣性滑動總是在scroll_update 中處理。由於 snap_fling 帶 snap 特性,停止時會自動對齊到內部元素。
chromium的 blink 分離過程還未完成,導致實現 snap_fling 的代碼有兩處,思路基本一致,這裡以 blink 新實現的代碼為例
src/ui/events/blink/input_handler_proxy.cc
snap_fling實現的邏輯流程
第二個環節處為 snap_fling 實現邏輯的關鍵點
第一個劃重點區,調用計算 snap_fling 終點的函數,用 gesture_event 中從用戶操作中獲得的動量,估算一個滑動距離,用 current_position +估算距離 ending_displacement 算出估計終點,再調用 FindSnapPosition 的方法,計算距離估計終點最近的 snap_position,將得到的點作為 target_offset 傳給 curve。
SnapFlingCurve保證自動滑動動畫能平滑輸出。方法為根據慣性滑動起終點信息,每個time_tick,curve 都會給出相應滑動距離,結果交給 Animation 輸出滑動動畫,直至target_offset 結束慣性滑動。
scroll-snap-element的實現方案
為了讓慣性滑動固定停在滑動方向上下一個 area,需要傳入一個方向參數。而FindSnapPosition 沒有獲取方向的途徑,通過傳參使其獲得方向參數。最後構造FindNextSnapPosition,計算出滑動方向上下一個 area 的 snap_position。
判斷 scroll-snap-element 的 value 是否為 next,是則走新建立的邏輯流程,否則走原來的流程,不影響原生的 snap_fling 操作。
小結
頁面滑動這類基礎操作,以漸進增強的方式在瀏覽器底層實現也是現在的趨勢,希望我們提出的屬性,能讓瀏覽器給用戶更優質的基礎體驗。
推薦閱讀:
※MVVM基本實現
※前端面試小記
※前端菜鳥筆記003-浮動
※Web前端知識體系梳理
※Angular 實戰教程 - Today (Part 3)