use-gesture 及 event threshold
為了簡化 event binding,我們選擇使用簡單的 use-gesture。
事後才發現其實沒有簡化多少,可以完全自己來
這裡我們只簡單綁定幾個事件:
- onClick:單擊關閉控制元件層、雙擊縮放
- onDrag:拖曳(pan)圖片,根據縮放狀態不同有不同行為
- onDragEnd:計算是否需要關閉 Lightbox,或是將圖片拉回 boundary 內。
- onWheel/onWheelEnd 將 macOS 的觸控板事件綁到 onDrag/onDragEnd 上。實際上 onWheelEnd 是模擬事件,並沒有辦法精確知道手勢放開的時間點。但 use-gesture 在模擬計算上處理得還可以,80% 狀況下不會意識到差異。
- onMove:在滑鼠移動時重新顯示控制元件。
- onPinch:處理多點觸控的縮放事件。
- onPinchEnd:多點觸控的縮放結束事件,用來將圖片拉回 boundary 內。
- onDragStart:阻止電腦觸發圖片 drag-n-drop 行為(例如把圖片拉下來存到桌面)。
Pinch 的處理算是我覺得用 use-gesture 用對的地方。API 提供的事件位置很方便。
但除此之外還是做了不少額外處理。
像是圖片的 boundary 處理(在圖片拉超過畫面時彈回來)主流做法有兩種:rubber band 彈力係數,在拖曳還沒結束前就提供阻力,超過邊緣越多圖片會動得越少(iOS 常用)。或是在超過邊緣後就不再提供拖曳(Android 常用,一般會搭配一點點邊緣顏色變化讓使用者知道這個邊緣過不去)。
考慮到邊緣其實跟縮放有關,為了簡化計算我們沒有使用 use-gesture 內建的 boundary 跟 rubber band,而是在使用者放開手勢後再將圖片彈回邊緣內。這麼做有幾個好處:
- 拖曳計算簡單而且迅速
精準不易疼痛,event movement 跟 image movement 基本上是 1:1。 - 不會有回彈過頭的問題(rubber band 沒有處理好很容易發生在回彈之後圖片跑出另一側邊緣的狀況)。
- 在因為其他手勢(例如 double tap zooming)撞擊到邊緣時不需要中斷動畫,等動畫結束後再拉回來就好。這可以避免兩個動畫之間彼此對抗,讓圖片彈來彈去。