AiCanvas
Canvas
Pannable, zoomable workflow canvas with grid, snap-to-grid, and fit-view.
Scroll to zoom · Shift+drag to pan · Drag nodes to reposition
100%
Usage
<script setup lang="ts">
const canvasRef = ref()
const zoom = ref(1)
const nodes = reactive([
{ id: 'n1', label: 'Query', x: 40, y: 80, status: 'completed' },
{ id: 'n2', label: 'Retrieve', x: 220, y: 80, status: 'running' },
])
</script>
<template>
<div class="relative">
<AiCanvas
ref="canvasRef"
height="400px"
snap-to-grid
:zoom="zoom"
@zoom="zoom = $event"
>
<template #default="{ zoom: canvasZoom, panX, panY }">
<svg class="pointer-events-none absolute inset-0">
<AiEdge
id="e1"
:source-x="152"
:source-y="104"
:target-x="220"
:target-y="104"
animated
/>
</svg>
<AiNode
v-for="node in nodes"
:key="node.id"
v-bind="node"
:zoom="canvasZoom"
:pan-x="panX"
:pan-y="panY"
@move="(id, x, y) => { const n = nodes.find(n => n.id === id); if (n) { n.x = x; n.y = y } }"
/>
</template>
</AiCanvas>
<AiControls
:zoom="zoom"
class="absolute bottom-3 right-3"
@zoom-in="canvasRef?.zoomIn()"
@zoom-out="canvasRef?.zoomOut()"
@reset="canvasRef?.resetView()"
@fit-view="canvasRef?.fitView(nodes.map(n => ({ x: n.x, y: n.y })))"
/>
</div>
</template>
<!-- Exposed: zoomIn, zoomOut, resetView, fitView(positions), clientToCanvas(x, y) -->Props
| Prop | Type | Default | Description |
|---|---|---|---|
| width | string | '100%' | Canvas container width |
| height | string | '500px' | Canvas container height |
| zoom | number | 1 | Controlled zoom level (sync with @zoom) |
| panX | number | 0 | Horizontal pan offset in px |
| panY | number | 0 | Vertical pan offset in px |
| minZoom | number | 0.1 | Minimum zoom (wheel / pinch) |
| maxZoom | number | 3 | Maximum zoom (wheel / pinch) |
| gridSize | number | 20 | Dot grid spacing in px |
| showGrid | boolean | true | Show background dot grid |
| snapToGrid | boolean | false | Snap click / drag coords to grid |
Events
| Event | Payload |
|---|---|
| @zoom | number |
| @pan | x: number, y: number |
| @click | x: number, y: number |
| @select | ids: string[] |
Slots
defaultbackgroundminimap