preloader
心得

Web Gesture: Zoom-Pan Scroll Strategy | 網頁手勢縮放 Zoom-Pan Scroll 策略學習筆記

Web Gesture: Zoom-Pan Scroll Strategy | 網頁手勢縮放 Zoom-Pan Scroll 策略學習筆記

1. CSS Transform 不影響 Layout

這是最關鍵的概念:

transform: scale(2);  /* 視覺上放大 2 倍,但元素在 layout 中的尺寸不變 */

瀏覽器的排版引擎(layout engine)完全忽略 transform,所以父容器的捲動範圍不會因為子元素放大而改變。這就是為什麼需要用 margin 手動補上差額。


2. transform-origin 決定放大方向

transform-origin: 0 0;   /* 從左上角開始放大,內容向右下擴展 */
transform-origin: center; /* 預設,從中心放大,四個方向都會擴展 */

0 0 是因為搭配 overflow: auto 時,捲動只能處理「向右」和「向下」的溢出。如果從中心放大,向左和向上的部分會被截掉。


3. Margin 撐大捲動範圍

原始寬度: 400px, scale: 2
視覺寬度: 800px, 但 layout 寬度仍是 400px
margin-right: 400 × (2-1) = 400px
layout 總寬度: 400 + 400 = 800px ← 捲動範圍正確了

這是一個 workaround,因為瀏覽器不提供「告訴 layout 我的 transform 後尺寸」的 API。


4. offsetWidth vs scrollHeight vs clientHeight

屬性 意義
offsetWidth 元素的 layout 寬度(含 border、padding)
scrollHeight 元素的完整內容高度(含溢出不可見部分)
clientHeight 元素可見區域高度(不含 scrollbar)

scrollHeight 而非 offsetHeight 是因為報表內容可能本來就超過一頁。


5. Touch Action 與手勢衝突

touch-action: pan-x pan-y;  /* 允許瀏覽器處理捲動,但禁用瀏覽器的 pinch-zoom */
touch-action: manipulation;  /* 允許捲動和 pinch,禁用 double-tap-to-zoom */
touch-action: none;          /* 全部由 JS 處理 */

Scroll 策略用 pan-x pan-y:讓瀏覽器負責捲動,Hammer 只處理 pinch 縮放。


6. CSS zoom 為什麼不能用

CSS zoom 會真正改變 layout,理論上更適合,但:

  • iOS Safari 對 Shadow DOM 內的 zoom 支援有問題

  • 不是 CSS 標準屬性(雖然 Chrome/Safari 支援)

  • MDN: zoom — 注意相容性表格


建議學習順序

  1. CSS Box Model + overflow — 理解捲動範圍怎麼算
  2. CSS Transform + transform-origin — 理解為什麼 transform 不影響 layout
  3. touch-action — 理解瀏覽器手勢和 JS 手勢的分工
  4. Element 尺寸 API — offsetWidth/scrollHeight/clientHeight 的差異
  5. HammerJS 文件hammerjs.github.io pinch/pan 辨識器設定

掌握前 3 點就能理解 scroll 策略的設計邏輯。


Transform 策略 vs Scroll 策略 對照表

Transform Scroll
縮放對象 元素本身 子元素
平移方式 Hammer 手動計算 瀏覽器原生捲動
適用場景 單張圖片 可捲動的長內容
使用處 燈箱式觀看效果的圖片(不須捲動) div