Core Concepts

Canvas Engine

The canvas is an SVG-based vector workspace with infinite pan/zoom, real-time rendering, and support for complex element hierarchies.

Infinite Canvas

Pan and zoom without boundaries. Virtual viewport renders only visible elements.

SVG Rendering

Vector-based rendering for infinite scalability and crisp exports at any resolution.

Real-time Updates

60fps rendering with optimistic updates. Changes reflect immediately.

Multi-selection

Select multiple elements with click+drag or Shift+click for batch operations.

Coordinate System
Understanding canvas coordinates and transformations
// Canvas coordinate system
// Origin (0,0) is at the center of the canvas
// X increases to the right, Y increases downward

┌────────────────────────────────────────┐
│              -Y (up)                   │
│                 ↑                      │
│                 │                      │
│  -X (left) ←────┼────→ +X (right)     │
│                 │                      │
│                 ↓                      │
│              +Y (down)                 │
└────────────────────────────────────────┘

// Element position is relative to canvas origin
interface Position {
  x: number  // Horizontal position
  y: number  // Vertical position
}

// Screen coordinates are converted to canvas coordinates
// accounting for zoom and pan offset
function screenToCanvas(screenX: number, screenY: number): Position {
  return {
    x: (screenX - panOffset.x) / zoom,
    y: (screenY - panOffset.y) / zoom
  }
}
Canvas API
Programmatic canvas manipulation
// Canvas navigation API

// Set zoom level (0.1 to 10)
canvas.setZoom(1.5) // 150% zoom

// Zoom to fit all elements
canvas.zoomToFit()

// Zoom to specific element
canvas.zoomToElement(elementId)

// Pan to position
canvas.panTo({ x: 500, y: 300 })

// Reset view to default
canvas.resetView()

// Get current viewport state
const viewport = canvas.getViewport()
// { x: 0, y: 0, width: 1920, height: 1080, zoom: 1 }

// Animate viewport change
canvas.animateTo({
  x: 100,
  y: 100,
  zoom: 2,
  duration: 300, // ms
  easing: 'easeInOut'
})
Keyboard Shortcuts
Navigation and manipulation shortcuts
Pan canvasSpace + Drag
Zoom in/outScroll
Reset zoom to 100%Cmd/Ctrl + 0
Fit to screenCmd/Ctrl + 1
Select all elementsCmd/Ctrl + A
Deselect allEscape
Delete selectedDelete/Backspace
Duplicate selectedCmd/Ctrl + D
Group selectedCmd/Ctrl + G
UngroupCmd/Ctrl + Shift + G
Rendering Pipeline
How elements are rendered to the canvas
// Rendering pipeline overview

┌─────────────┐     ┌─────────────┐     ┌─────────────┐
│   Elements  │ ──▶ │   Filter    │ ──▶ │    Sort     │
│   (state)   │     │ (viewport)  │     │  (z-order)  │
└─────────────┘     └─────────────┘     └─────────────┘
                                               │
                                               ▼
┌─────────────┐     ┌─────────────┐     ┌─────────────┐
│   Output    │ ◀── │   Compose   │ ◀── │   Render    │
│   (DOM)     │     │   (layers)  │     │  (to SVG)   │
└─────────────┘     └─────────────┘     └─────────────┘

// Pipeline stages:
// 1. Elements: Get all elements from state
// 2. Filter: Remove elements outside viewport (virtualization)
// 3. Sort: Order by z-index for correct layering
// 4. Render: Convert each element to SVG markup
// 5. Compose: Combine into layer groups
// 6. Output: React renders to DOM

// Performance optimizations:
// - React.memo for element components
// - useMemo for transform calculations
// - requestAnimationFrame for smooth updates
// - Will-change hints for GPU acceleration
Canvas Events
Event handling and interaction callbacks
// Canvas event system

interface CanvasEvents {
  // Mouse/pointer events
  onClick: (position: Position, element?: DesignElement) => void
  onDoubleClick: (position: Position, element?: DesignElement) => void
  onMouseDown: (position: Position) => void
  onMouseMove: (position: Position) => void
  onMouseUp: (position: Position) => void
  
  // Element events
  onElementAdd: (element: DesignElement) => void
  onElementUpdate: (element: DesignElement, changes: Partial<DesignElement>) => void
  onElementDelete: (elementId: string) => void
  
  // Selection events
  onSelectionChange: (selection: DesignElement[]) => void
  
  // Viewport events
  onZoom: (zoom: number) => void
  onPan: (offset: Position) => void
  
  // Drag events
  onDragStart: (element: DesignElement, position: Position) => void
  onDrag: (element: DesignElement, position: Position) => void
  onDragEnd: (element: DesignElement, position: Position) => void
}

// Usage example
<Canvas
  elements={elements}
  onElementAdd={(el) => console.log('Added:', el.id)}
  onSelectionChange={(sel) => setSelected(sel)}
  onZoom={(zoom) => setZoomLevel(zoom)}
/>

Related Documentation