A FabricJS library, facilitating working above coordinate planes
npm install @ajoslin103/schematicA lightweight Fabric.js library for working with canvas objects on an interactive coordinate grid.

- Interactive coordinate grid with pan, zoom, and configurable units (points, imperial, metric)
- Built on Fabric.js v6+ – full access to Fabric's powerful canvas API
- Mouse/touch interactions – wheel zoom, right-click panning, optional origin pinning
- TypeScript support with full type definitions
- Flexible architecture – use high-level Schematic or low-level Map API
- Debug system with granular logging categories
- Zero dependencies (except Fabric.js peer dependency)
```
Your App → Schematic → Map → Fabric Canvas
↓
Grid (renders behind objects)
Schematic – Main entry point with event system and interaction controls
Map – Manages Fabric canvas lifecycle and grid synchronization
Grid – Renders coordinate grid, axes, and labels beneath Fabric objects
Base – Shared configuration foundation for all components
`bash`
npm install @ajoslin103/schematic fabricor
yarn add @ajoslin103/schematic fabric
Requirements:
- Fabric.js ^6.7.1 (peer dependency)
- Modern browser with ES6+ support
Package exports:
- ESM: dist/schematic.esm.jsdist/schematic.cjs.js
- CommonJS: dist/schematic.umd.js
- UMD: dist/types/index.d.ts
- TypeScript types:
`javascript
import { Schematic } from '@ajoslin103/schematic';
import * as fabric from 'fabric';
const container = document.getElementById('canvas-container');
const schematic = new Schematic(container, {
gridEnabled: true,
units: 'points',
zoomDebounceDelay: 200
});
// Access the Fabric canvas
const canvas = schematic.fabricCanvas;
// Configure zoom behavior
schematic.setZoomLimits(0.1, 10);
schematic.setZoom(1);
// Add Fabric objects
const rect = new fabric.Rect({
left: 100,
top: 100,
width: 200,
height: 150,
fill: '#4CAF50'
});
canvas.add(rect);
`
`typescript
import { Schematic, SchematicOptions } from '@ajoslin103/schematic';
import { Rect } from 'fabric';
const container = document.getElementById('canvas-container');
if (!container) throw new Error('Container not found');
const options: SchematicOptions = {
gridEnabled: true,
units: 'imperial',
mouseWheelZoom: true,
zoomOnCenter: false
};
const schematic = new Schematic(container, options);
// Configure
schematic.setZoomLimits(0.1, 10);
schematic.setShowGrid(true);
schematic.setUnits('metric');
// Add objects with type safety
const rect = new Rect({
left: 50,
top: 50,
width: 100,
height: 100,
fill: 'rgba(255, 99, 71, 0.8)'
});
schematic.fabricCanvas.add(rect);
`
`javascript
// Listen to zoom events
schematic.on('zoom:change', (data) => {
console.log('Zoom changed:', data.zoom);
});
schematic.on('zoom:completed', (data) => {
console.log('Zoom completed:', data.zoom);
});
// Listen to pan events
schematic.on('pan:completed', (data) => {
console.log('Pan completed:', data);
});
// Grid visibility changes
schematic.on('grid:change', (data) => {
console.log('Grid visibility:', data.enabled);
});
`
`javascript
// Pin origin to corner (locks grid to viewport)
schematic.setOriginPin('TOP_LEFT', 15);
// Options: 'TOP_LEFT', 'TOP_RIGHT', 'BOTTOM_LEFT', 'BOTTOM_RIGHT', 'CENTER', 'NONE'
// Reset view to initial state
schematic.resetView();
// Toggle grid visibility
schematic.setShowGrid(false);
// Change units dynamically
schematic.setUnits('metric'); // 'points' | 'imperial' | 'metric'
// Control zoom behavior
schematic.setZoomOnCenter(true); // Zoom around center vs mouse position
`
Constructor:
`typescript`
new Schematic(container: HTMLElement, options?: SchematicOptions)
Properties:
- fabricCanvas – Fabric.js Canvas instancemapInstance
- – Underlying Map instancegridEnabled
- – Grid visibility statezoomOnCenter
- – Zoom around center vs mouseunits
- – Current unit system
Methods:
- setZoom(zoom: number) – Set zoom levelsetZoomLimits(min: number, max: number)
- – Clamp zoom rangesetShowGrid(enabled: boolean)
- – Toggle grid visibilitysetOriginPin(pin: string, margin: number)
- – Pin origin to cornersetUnits(units: 'points' | 'imperial' | 'metric')
- – Change unitssetZoomOnCenter(enabled: boolean)
- – Control zoom anchorresetView()
- – Reset to initial viewon(event: string, callback: Function)
- – Subscribe to eventoff(event: string, callback?: Function)
- – Unsubscribeemit(event: string, data: any)
- – Emit custom event
Events:
- zoom – Zoom in progresszoom:change
- – Zoom changedzoom:completed
- – Zoom finishedpan:move
- – Pan in progresspan:completed
- – Pan finishedgrid:change
- – Grid visibility changedview:reset
- – View reset triggered
Constructor:
`typescript`
new Map(container: HTMLElement, options?: BaseOptions)
Methods:
- setZoom(zoom: number) – Set zoomonResize(width: number, height: number)
- – Handle resizeupdate()
- – Force grid syncreset()
- – Reset viewport
Properties:
- visible – Grid visibilityunits
- – Unit systemstep
- – Grid step sizescale
- – Grid scale
Methods:
- setUnits(units: string) – Change unitsshow(visible?: boolean)
- – Show/hide gridrender()
- – Force redraw
The library includes a centralized debug system that allows you to control console output by category. By default, all debug logging is disabled for production use.
`javascript`
const schematic = new Schematic(container, {
debug: true // Enable all debug categories
});
`javascript`
const schematic = new Schematic(container, {
debug: {
schematic: true, // Schematic-level operations
events: true, // Mouse/interaction events
grid: false, // Grid rendering
map: false, // Map updates
units: false, // Unit conversions
calibration: false // Calibration tools
}
});
`javascript
// Enable a category at runtime
schematic.debug.enable('events');
// Disable a category
schematic.debug.disable('grid');
// Enable all
schematic.debug.enable('all');
// Check if enabled
if (schematic.debug.isEnabled('units')) {
console.log('Units debug enabled');
}
`
Mouse:
- Scroll wheel – Zoom in/out (with configurable limits)
- Alt/Option + scroll – Zoom around cursor position
- Right-click + drag – Pan canvas (or Ctrl+Left on macOS)
- Left-click – Select/interact with Fabric objects
Programmatic:
- setZoom(), setZoomLimits() – Control zoomsetOriginPin()
- – Lock origin to viewport cornerresetView()
- – Return to initial state
Setup:
`bash`
git clone https://github.com/ajoslin103/schematic.git
cd schematic
npm install
Scripts:
- npm run dev – Start dev server with live reloadnpm run build
- – Build all bundles (CJS, ESM, UMD) + typesnpm run watch
- – Watch mode for developmentnpm run serve
- – Serve demo files
Project Structure:
``
src/
├── core/ # Schematic, Base, Debug, Constants
├── map/ # Map class
├── grid/ # Grid rendering
├── geometry/ # Point utilities
├── components/ # Calibration tools
└── lib/ # Helper functions
- Grid renders in Fabric's before:render` phase and never mutates Fabric objects
- Grid Y-axis is inverted for display; Fabric world coordinates remain standard
- Integer snapping enabled by default for object positioning
- TypeScript definitions included for full IDE support
Built on the foundation of IndoorJS by Mudin.
MIT © Allen Joslin