Cross-framework drawing canvas library for brainstorming and simple sketching
npm install drawfnCross-framework drawing canvas library for brainstorming and simple sketching.
- 🎨 Framework-agnostic core (works with React, Svelte, Vue, vanilla JS)
- ✏️ Multiple drawing tools: pen, shapes, text, images, and more
- 📐 Element-based retained-mode architecture
- 💾 Full scene serialization to JSON
- ⏮️ Undo/redo support
- 📤 Export to PNG and SVG
- 🔍 Pan and zoom with viewport culling
- 🎯 Selection and transformation tools
``bash`
npm install @21n/drawfn perfect-freehand
`typescript
import { Drawfn } from '@21n/drawfn';
const canvas = document.querySelector('canvas');
const drawfn = new Drawfn({ canvas });
// Set a tool
drawfn.setTool('pen');
// Listen to events
drawfn.on('elementAdded', (element) => {
console.log('New element added:', element);
});
// Export the scene
const scene = drawfn.getScene();
console.log(scene);
`
- select: Select, move, resize, and rotate elements with handles
- pan: Pan the canvas with mouse/trackpad
- pen: Freehand drawing with pressure support (perfect-freehand)
- rectangle: Draw rectangles (hold Shift for squares)
- ellipse: Draw ellipses (hold Shift for circles)
- arrow: Draw arrows with arrowhead
- text: Add text with inline editing overlay
- image: Add images programmatically
- node: Add Nucleus node bookmarks (for integrations)
`typescript`
const drawfn = new Drawfn({
canvas: HTMLCanvasElement,
overlayRoot?: HTMLElement, // For text editing overlay
getImageBitmap?: (src: string) => Promise
});
Scene Management
- load(scene: Scene): Load a scene from JSONgetScene(): Scene
- : Get current scene as JSONclear()
- : Clear the entire canvas
Element Operations
- add(element: Element): string: Add an element, returns IDupdate(id: string, patch: Partial
- : Update an elementremove(id: string)
- : Remove an elementbringToFront(id: string)
- : Move element to top layersendToBack(id: string)
- : Move element to bottom layergetElements(): Element[]
- : Get all elementsgetElementById(id: string): Element | undefined
- : Get element by ID
Tool Management
- setTool(tool: ToolName, opts?): Set active toolimage
- For tool: setTool('image', { src: 'url', naturalW: 200, naturalH: 150 })node
- For tool: setTool('node', { nodeId: 'abc', preview: { title: 'Note' } })getTool(): ToolName
- : Get current tool
Camera & View
- setCamera(camera: Partial: Update camera position/zoomgetCamera(): Camera
- : Get camera statescreenToCanvas(point: Point): Point
- : Convert screen to canvas coordinates
History
- undo(): Undo last actionredo()
- : Redo last undone action
Selection
- setSelection(ids: string[]): Set selected element IDsgetSelectedIds(): string[]
- : Get selected element IDs
Export
- exportPNG(opts?): Promise: Export as PNG{ padding?: number; scale?: number; transparent?: boolean }
- Options: exportSVG(opts?): Promise
- : Export as SVG (includes freedraw, arrows, images){ padding?: number; scale?: number }
- Options:
Events
- on(event, handler): () => void: Subscribe to events, returns unsubscribe functionpointerDown
- Events: , pointerMove, pointerUp, elementAdded, elementUpdated, elementRemoved, selectionChanged, historyChanged, cameraChanged
Cleanup
- destroy(): Cleanup and remove event listeners
See example.html for a complete vanilla JS example with toolbar and all tools.
For React examples, see @21n/drawfn-react` package.
- Delete/Backspace: Delete selected elements
- Cmd/Ctrl+Z: Undo
- Cmd/Ctrl+Shift+Z or Cmd/Ctrl+Y: Redo
- Space+Drag: Pan (when not in pan tool mode)
- Shift+Drag: Constrain aspect ratio for shapes
- Wheel: Zoom at cursor position
- Click+Drag: Tool-specific interaction
- Shift+Click: Multi-select (in select tool)
Apache-2.0