Grid & Ruler Overlay
A grid built from Line shapes lives in world space, so it pans and zooms
with your content. Put it on its own layer created first (child order is paint
order, so it sits behind everything) and rebuild it whenever the scene size changes.
import { Stage, Line } from '@veyrajs/core'
const container = document.querySelector('#app') as HTMLElementconst stage = new Stage({ container, width: 800, height: 480, background: '#0b1220' })
const gridLayer = stage.createLayer() // created first → paints behindconst contentLayer = stage.createLayer()
function drawGrid(step = 32, color = '#1e293b') { gridLayer.removeChildren() // clear old lines before redrawing const { width, height } = stage
for (let x = 0; x <= width; x += step) { gridLayer.add(new Line({ points: [{ x, y: 0 }, { x, y: height }], stroke: color, strokeWidth: 1 })) } for (let y = 0; y <= height; y += step) { gridLayer.add(new Line({ points: [{ x: 0, y }, { x: width, y }], stroke: color, strokeWidth: 1 })) }}
drawGrid()For a ruler or HUD that stays put regardless of camera pan/zoom, use an Overlay instead: its
drawOps() are screen-space and drawn after the scene each frame.
import type { Overlay, DrawOp } from '@veyrajs/core'
const ruler: Overlay = { drawOps(): DrawOp[] { const ops: DrawOp[] = [] for (let x = 0; x <= stage.width; x += 50) { ops.push({ type: 'text', x: x + 2, y: 2, text: String(x), font: '10px system-ui', fill: '#64748b' }) } return ops },}stage.addOverlay(ruler)The grid is part of the scene (it moves with the world); the overlay is fixed to the screen — pick by
whether the marks should track the content or the viewport. Remove the overlay later with
stage.removeOverlay(ruler).
Related
Section titled “Related”- Shapes (API) —
Linegeometry. - Scene Graph (API) —
Overlay,addOverlay, layers. - Rendering (API) — the
DrawOpvocabulary.