openseadragon-fabric-overlay
v2.0.0
Published
OpenSeadragon plugin for adding a Fabric.js overlay with drawing and annotation support.
Downloads
69
Maintainers
Readme
OpenSeadragon Fabric Overlay
A powerful plugin that seamlessly integrates FabricJS with OpenSeadragon, enabling interactive annotations, drawings, and shape manipulation on top of deep-zoom images.
⚠️ Version 2.0 Breaking Changes: This version uses Fabric.js 7.x. Import syntax changed from
fabric.Rectto named imports likeimport { Rect } from 'fabric'.Note: This library automatically sets default object origins to
left/topfor intuitive positioning. In Fabric.js 7.x, the default changed tocenter/center. You can override this by passingdefaultObjectOriginin the config:const overlay = initOSDFabricOverlay(viewer, { defaultObjectOrigin: { originX: 'center', originY: 'center' } });
Live Demo | Report Bug | Request Feature
Features
- ✨ Interactive Annotations - Add shapes, text, and drawings that scale with image zoom
- 🎨 Full FabricJS Support - Access all FabricJS features and objects
- 🖱️ Freehand Drawing - Built-in support for pencil, spray, and custom brushes
- 📐 Shape Tools - Rectangles, circles, polygons, lines, and more
- 🔄 Automatic Synchronization - Overlay stays perfectly aligned during pan and zoom
- 📦 TypeScript Support - Full type definitions included
- 🪶 Lightweight - Minimal overhead, maximum performance
- 🔧 Highly Configurable - Customize every aspect of the overlay
Installation
npm install openseadragon-fabric-overlayPeer Dependencies
Ensure you have the required peer dependencies installed:
npm install openseadragon fabric@^7.1.0Note: Version 2.x requires Fabric.js 7.x. For Fabric.js 6.x support, use version 1.x.
Quick Start
import OpenSeadragon from "openseadragon";
import { Rect } from "fabric";
import { initOSDFabricOverlay } from "openseadragon-fabric-overlay";
// Initialize OpenSeadragon viewer
const viewer = OpenSeadragon({
id: "viewer",
prefixUrl: "//openseadragon.github.io/openseadragon/images/",
tileSources: "//openseadragon.github.io/example-images/highsmith/highsmith.dzi",
});
// Create fabric overlay
const overlay = initOSDFabricOverlay(viewer, {
fabricCanvasOptions: {
selection: true,
},
});
// Add a rectangle
const rect = new Rect({
left: 100,
top: 100,
width: 200,
height: 150,
fill: "rgba(255, 0, 0, 0.3)",
stroke: "#ff0000",
strokeWidth: 2,
});
overlay.fabricCanvas().add(rect);API Reference
initOSDFabricOverlay
Initialize the fabric overlay on an OpenSeadragon viewer.
function initOSDFabricOverlay(
viewer: OpenSeadragon.Viewer,
options?: FabricOverlayOptions,
overlayId?: string
): FabricOverlayParameters:
viewer- OpenSeadragon viewer instanceoptions- Configuration options (optional)fabricCanvasOptions- Options passed to FabricJS canvas constructor
overlayId- Unique identifier for the overlay (optional)
Returns: FabricOverlay instance
FabricOverlay Methods
fabricCanvas()
Get the underlying FabricJS canvas instance.
overlay.fabricCanvas(): fabric.Canvasresize()
Manually trigger a resize of the overlay canvas.
overlay.resize(): voidclear()
Remove all objects from the canvas.
overlay.fabricCanvas().clear();Usage Examples
Adding Shapes
Rectangle
const rect = new Rect({
left: 200,
top: 200,
width: 300,
height: 200,
fill: "rgba(0, 123, 255, 0.2)",
stroke: "#007bff",
strokeWidth: 3,
});
overlay.fabricCanvas().add(rect);Circle
const circle = new Circle({
left: 500,
top: 300,
radius: 100,
fill: "rgba(40, 167, 69, 0.2)",
stroke: "#28a745",
strokeWidth: 3,
});
overlay.fabricCanvas().add(circle);Text
const text = new Text("Hello World", {
left: 300,
top: 400,
fontSize: 40,
fill: "#333",
fontFamily: "Arial",
});
overlay.fabricCanvas().add(text);Polygon
const polygon = new Polygon(
[
{ x: 100, y: 100 },
{ x: 200, y: 50 },
{ x: 300, y: 100 },
{ x: 250, y: 200 },
{ x: 150, y: 200 },
],
{
fill: "rgba(255, 193, 7, 0.2)",
stroke: "#ffc107",
strokeWidth: 2,
}
);
overlay.fabricCanvas().add(polygon);Freehand Drawing
Enable drawing mode with a pencil brush:
// Disable OpenSeadragon mouse navigation
viewer.setMouseNavEnabled(false);
const canvas = overlay.fabricCanvas();
// Configure pencil brush
canvas.freeDrawingBrush = new PencilBrush(canvas);
canvas.freeDrawingBrush.width = 5;
canvas.freeDrawingBrush.color = "#000000";
canvas.isDrawingMode = true;
// To disable drawing mode
canvas.isDrawingMode = false;
viewer.setMouseNavEnabled(true);Spray Brush
canvas.freeDrawingBrush = new SprayBrush(canvas);
canvas.freeDrawingBrush.width = 10;
canvas.freeDrawingBrush.color = "#ff0000";
canvas.isDrawingMode = true;Object Selection and Manipulation
// Enable selection
overlay.fabricCanvas().selection = true;
// Listen to selection events
overlay.fabricCanvas().on("selection:created", (e) => {
console.log("Object selected:", e.selected);
});
overlay.fabricCanvas().on("object:modified", (e) => {
console.log("Object modified:", e.target);
});
// Get active object
const activeObject = overlay.fabricCanvas().getActiveObject();
// Remove active object
if (activeObject) {
overlay.fabricCanvas().remove(activeObject);
}Serialization and Deserialization
Save and restore canvas state:
// Save canvas to JSON
const json = overlay.fabricCanvas().toJSON();
localStorage.setItem("canvas", JSON.stringify(json));
// Load canvas from JSON
const savedJson = JSON.parse(localStorage.getItem("canvas"));
overlay.fabricCanvas().loadFromJSON(savedJson, () => {
overlay.fabricCanvas().renderAll();
});Custom Object Properties
const rect = new Rect({
left: 100,
top: 100,
width: 200,
height: 100,
fill: "blue",
// Custom properties
id: "my-rect-1",
metadata: {
type: "annotation",
author: "John Doe",
timestamp: Date.now(),
},
});
overlay.fabricCanvas().add(rect);
// Access custom properties
rect.on("selected", () => {
console.log(rect.id, rect.metadata);
});Event Handling
const canvas = overlay.fabricCanvas();
// Mouse events
canvas.on("mouse:down", (e) => console.log("Mouse down", e.pointer));
canvas.on("mouse:move", (e) => console.log("Mouse move", e.pointer));
canvas.on("mouse:up", (e) => console.log("Mouse up", e.pointer));
// Object events
canvas.on("object:added", (e) => console.log("Object added", e.target));
canvas.on("object:removed", (e) => console.log("Object removed", e.target));
canvas.on("object:modified", (e) => console.log("Object modified", e.target));
// Selection events
canvas.on("selection:created", (e) => console.log("Selection created"));
canvas.on("selection:cleared", (e) => console.log("Selection cleared"));Advanced Configuration
Custom Canvas Options
const overlay = initOSDFabricOverlay(viewer, {
fabricCanvasOptions: {
selection: true,
backgroundColor: "rgba(255, 255, 255, 0.1)",
renderOnAddRemove: true,
enableRetinaScaling: true,
allowTouchScrolling: false,
preserveObjectStacking: true,
},
scale: 1000,
});Coordinate Conversion
Convert between viewport and canvas coordinates:
// OpenSeadragon viewport point to canvas point
const viewportPoint = viewer.viewport.pointFromPixel(
new OpenSeadragon.Point(100, 100)
);
const canvasPoint = {
x: viewportPoint.x * overlay.fabricCanvas().getWidth(),
y: viewportPoint.y * overlay.fabricCanvas().getHeight(),
};Best Practices
Disable Mouse Navigation During Drawing
viewer.setMouseNavEnabled(false); // When drawing viewer.setMouseNavEnabled(true); // When doneOptimize Performance
// Disable rendering during bulk operations overlay.fabricCanvas().renderOnAddRemove = false; // Add multiple objects overlay.fabricCanvas().add(obj1, obj2, obj3); // Re-enable and render overlay.fabricCanvas().renderOnAddRemove = true; overlay.fabricCanvas().renderAll();Clean Up Event Listeners
// Remove specific listener canvas.off("mouse:down", handler); // Remove all listeners for an event canvas.off("mouse:down");
Limitations
- Static FabricJS canvases are not supported
- For non-interactive overlays, disable interactions via
fabricCanvasOptions
Browser Support
- Chrome (latest)
- Firefox (latest)
- Safari (latest)
- Edge (latest)
Contributing
Contributions are welcome! Please follow these steps:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Make your changes
- Update version in
package.json - Build the project (
npm run build) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
Development Setup
# Install dependencies
npm install
# Build the library
npm run build
# Run demo site locally
npm run dev
# Run tests
npm testTesting Locally
# Build the package
npm run build
# Link locally
npm link
# In your test project
npm link openseadragon-fabric-overlayPublishing
# Update version in package.json
npm version patch|minor|major
# Build and publish
npm run build
npm publishLicense
This project is licensed under the MIT License - see the LICENSE file for details.
Acknowledgments
This project is inspired by @altert's OpenseadragonFabricjsOverlay. The original package used JavaScript with Prototype-based functions, which caused type safety issues in strictly-typed codebases and was built for older OpenSeadragon versions.
@brunoocastro rewrote it in TypeScript as openseadragon-fabric. This package builds upon that work with optimizations and extended functionality.
Support
Made with ❤️ by Ravi Shankar Saini
