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-operationsimportOpenSeadragonfrom'openseadragon';import{createOSDAnnotator}from'@annotorious/openseadragon';import{mountPluginasmountBooleanPlugin}from'@annotorious/plugin-boolean-operations';import'@annotorious/openseadragon/annotorious-openseadragon.css';/** * Important: the plugin requires multi-select to be enabled! */constviewer=OpenSeadragon({/** Your viewer config **/multiSelect: true});constanno=createOSDAnnotator(viewer,{/* options */});// Initialize the pluginconstplugin=mountBooleanPlugin(anno);// Merge exampledocument.getElementById('merge').addEventListener('click',()=>{plugin.mergeSelected();});// Subtract exampledocument.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 bodiesplugin.mergeSelected({bodies: [myBody1,myBody2]});// Decide dynamically from the selectionplugin.mergeSelected({bodies: selected=>selected.flatMap(a=>a.bodies.filter(b=>b.purpose==='tagging'))});