iPad 上拖不動的圖譜節點:touch-action 對 SVG 子元素無效
首頁的知識圖譜可以拖曳節點——桌機上手感很好,iPad 上完全拖不動:手指一動,整頁跟著捲,拖曳中斷。
教科書解法為什麼失效
標準做法是對可拖曳元素設 touch-action: none,告訴瀏覽器「這個元素上的觸控手勢交給 JS,不要啟動捲動」。桌機的觸控模擬器一切正常——然後 iPad Safari 直接無視它。
原因藏在相容性表的註腳裡:iOS Safari 只在少數元素上尊重 touch-action,SVG 的子元素(circle、g)不在其中。瀏覽器接管了手勢當成捲動,pointer 事件序列被 pointercancel 腰斬,拖曳自然死了。
正解:回到 touch 事件的原始語意
修法是在命中元素上直接擋掉預設行為:
ts
el.addEventListener('touchstart', (e) => e.preventDefault(), { passive: false });
el.addEventListener('touchmove', (e) => e.preventDefault(), { passive: false });
兩個關鍵知識點:
- touch 事件永遠 target 觸摸起點的元素——就算手指移出元素範圍,
touchmove還是發給起點元素。所以只要在節點上攔截,整段拖曳都攔得住,不用去動全域。 passive: false不能省。現代瀏覽器為了捲動效能,touch listener 預設 passive——passive listener 裡的preventDefault()是無效的(還會噴警告)。
另外把節點的觸控命中範圍放大(透明的 hit circle,半徑加 14px)——手指不是滑鼠,Fitts 定律在觸控裝置上要用指腹的尺度重算。
這一類雷的共同教訓:「桌機瀏覽器的觸控模擬」與真機是兩個世界。觸控互動沒上過真 iPad,就不能說做完了。
讀到這裡若有一點收穫,替這顆種子澆一次水——匿名、一人一次。