背景網格用 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 開銷,是無限網格的最佳解。