背景網格用 backgroundImage 加 modulo 做無限延展

無限畫布的背景網格不要用元素畫,用 CSS background-image + background-size + background-position。網格無限延展、可跟著縮放與平移、零 DOM 元素、純 GPU 合成。

做法

const gridStep    = GRID_SIZE * scale
const gridOffsetX = ((offsetX % gridStep) + gridStep) % gridStep
const gridOffsetY = ((offsetY % gridStep) + gridStep) % gridStep
 
<div style={{
  backgroundImage: `radial-gradient(circle, rgba(255,255,255,0.18) 1px, transparent 1px)`,
  backgroundSize:  `${gridStep}px ${gridStep}px`,
  backgroundPosition: `${gridOffsetX}px ${gridOffsetY}px`,
}} />
  • backgroundImage:用 radial-gradient 畫一個 1px 的點(要線條格就用 linear-gradient
  • backgroundSize:一格的大小,乘以 scale 讓格子跟著縮放
  • backgroundPosition:用 modulo 把任意大的 offset 映射回 [0, gridStep)

為什麼要 modulo

CSS 背景圖會自動 tile(重複),所以 position 取餘數即可 — 視覺上偏移 offsetX 跟偏移 offsetX + gridStep 看起來一模一樣。直接傳 offsetX 也能跑,但數字會越拖越大、可能撞到精度上限。

處理負數

((x % step) + step) % step 是 JavaScript 取「永遠為正」的餘數的標準寫法。原生 % 對負數會回傳負餘數(-5 % 3 === -2),會讓網格往錯邊偏移一格。

為什麼不用元素或 SVG 畫

  • 元素:要算可視範圍 → 動態產生/刪除 N×M 個 div,平移時重建一次 → DOM 操作貴
  • SVG line:同樣問題,且 SVG re-render 不便宜
  • Canvas:可以,但要寫 drawImage 邏輯、自己處理 retina scaling

background-image 是瀏覽器 native tile,0 DOM、0 JS 開銷,是無限網格的最佳解。

相關