Adds functionality to merge and subtract annotation shapes.
Important: This plugin currently only supports
@annotorious/openseadragon. Support for plain (JPEG, PNG,...) images is not yet implemented. Join the discussion if you'd like to use this with@annotorious/annotoriousor@annotorious/react.
npm install @annotorious/plugin-boolean-operationsimport OpenSeadragon from 'openseadragon';
import { createOSDAnnotator } from '@annotorious/openseadragon';
import { mountPlugin as mountBooleanPlugin  } from '@annotorious/plugin-boolean-operations';
import '@annotorious/openseadragon/annotorious-openseadragon.css';
/**
 * Important: the plugin requires multi-select to be enabled!
 */
const viewer = OpenSeadragon({
  /** Your viewer config **/
  multiSelect: true
});
const anno = createOSDAnnotator(viewer, { /* options */ });
// Initialize the plugin
const plugin = mountBooleanPlugin(anno);
// Merge example
document.getElementById('merge').addEventListener('click', () => {
  plugin.mergeSelected();
});
// Subtract example
document.getElementById('subtract').addEventListener('click', () => {
  plugin.subtractSelected();
});| Method | Description | 
|---|---|
| canSubtractSelected() | Checks if the current selection allows subtraction (without producing an empty shape). | 
| mergeSelected(opts?: MergeOptions) | Merges all currently selected annotations. Accepts MergeOptions to control how annotation bodies are handled. | 
| subtractSelected() | Keeps the first selected annotation, clipping its geometry by subtracting all others. All other selected annotations are deleted. Selection order matters. | 
mergeSelected can be customized with a MergeOptions object that controls how annotation bodies are preserved in the merged shape.
You can either choose one of the built-in strategies or provide your own explicit override.
- { strategy: 'merge_bodies' }(default). Combine bodies from all selected shapes into the merged annotation, in the order of selection.
- { strategy: 'keep_first_bodies' }. Keep only the bodies from the first selected annotation, discard all others.
You can override the merge behavior by passing:
- An explicit array of AnnotationBodyobjects to keep.
- A function that receives the selected annotations and returns the bodies to keep.
// Keep specific bodies
plugin.mergeSelected({
  bodies: [myBody1, myBody2]
});
// Decide dynamically from the selection
plugin.mergeSelected({
  bodies: selected => selected.flatMap(a => a.bodies.filter(b => b.purpose === 'tagging'))
});