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')) });