Annotation Contexts
What is a context?
Section titled “What is a context?”An annotation context defines a scope where annotations exist — for example, multiple annotation and labelling tasks. Each context specifies which drawing tools are available and optionally limits how many annotations of each type can be created.
Annotation contexts are an extension of the core Annotation model, and are defined in the @osdlabel/annotation-context package.
Only one context is active at a time.
Defining contexts
Section titled “Defining contexts”import { createAnnotationContextId } from '@osdlabel/annotation-context';import type { AnnotationContext } from '@osdlabel/annotation-context';
const contexts: AnnotationContext[] = [ { id: createAnnotationContextId('buildings'), label: 'Buildings', // Only annotate buildings in specific regions imageIds: [createImageId('sample-1'), createImageId('sample-2')], tools: [ // Up to 10 building outlines per image { type: 'rectangle', maxCount: 10, countScope: 'per-image' }, // Up to 5 freehand boundaries total for irregular shapes { type: 'polyline', maxCount: 5 }, ], }, { id: createAnnotationContextId('roads'), label: 'Roads', tools: [ // Trace road segments with lines { type: 'line', maxCount: 20, countScope: 'per-image' }, // Mark intersections { type: 'point', maxCount: 15 }, ], }, { id: createAnnotationContextId('landmarks'), label: 'Landmarks', tools: [ { type: 'rectangle' }, { type: 'circle' }, { type: 'line' }, { type: 'point' }, { type: 'polyline' }, { type: 'freeHandPath' }, ], },];Tool constraints
Section titled “Tool constraints”Each tool in a context can have:
| Property | Type | Default | Description |
|---|---|---|---|
type | ToolType | (required) | 'rectangle' | 'circle' | 'line' | 'point' | 'polyline' | 'freeHandPath' |
maxCount | number | unlimited | Maximum number of annotations of this type |
countScope | CountScope | 'global' | Whether maxCount applies per-image or globally across all images |
defaultStyle | Partial<AnnotationStyle> | default style | Override the default stroke/fill for this tool |
When a tool’s maxCount is reached, it is automatically disabled in the toolbar and via keyboard shortcuts.
Count scope
Section titled “Count scope”The countScope property controls how annotations are counted against maxCount:
'global'(default) — Counts all annotations of this type across all images'per-image'— Counts annotations per image independently
{ type: 'line', maxCount: 3, countScope: 'per-image', // Each image can have up to 3 lines}Image scoping
Section titled “Image scoping”A context can be restricted to specific images using the imageIds property:
{ id: createAnnotationContextId('context1'), label: 'My context', imageIds: [createImageId('img-1'), createImageId('img-2')], tools: [{ type: 'line', maxCount: 3 }],}When the active cell shows an image not in the context’s imageIds, all tools are disabled. If imageIds is omitted, the context applies to all images.
Setting contexts
Section titled “Setting contexts”Pass contexts to the Annotator component or set them programmatically:
// Via Annotator component<Annotator images={images} contexts={contexts} />;
// Via actions (when using AnnotatorProvider)const { actions } = useAnnotator();actions.setContexts(contexts);actions.setActiveContext(contexts[0].id);Switching contexts
Section titled “Switching contexts”You can switch contexts programmatically using actions:
const { actions } = useAnnotator();actions.setActiveContext(contextId);
// Clear the active tool when switching contextsactions.setActiveTool(null);Or enable the built-in UI in the Annotator component:
<Annotator images={images} contexts={contexts} showContextSwitcher={true} />The ContextSwitcher component can also be used independently in custom layouts. See Components.
Displaying multiple contexts
Section titled “Displaying multiple contexts”By default, only the active context’s annotations are visible on the canvas. You can display annotations from additional contexts as a read-only overlay — visible but not selectable or editable.
Via the Annotator component
Section titled “Via the Annotator component”<Annotator images={images} contexts={contexts} displayedContextIds={[createAnnotationContextId('ctx1'), createAnnotationContextId('ctx2')]}/>Via actions (when using AnnotatorProvider)
Section titled “Via actions (when using AnnotatorProvider)”const { actions } = useAnnotator();actions.setDisplayedContexts([ createAnnotationContextId('ctx1'), createAnnotationContextId('ctx2'),]);The active context is always displayed regardless of displayedContextIds. Annotations from non-active displayed contexts are rendered on the canvas but cannot be selected, moved, or modified.
Reading constraint status
Section titled “Reading constraint status”Use the constraintStatus accessor to check which tools are enabled:
const { constraintStatus } = useAnnotator();
const status = constraintStatus();// status.rectangle.enabled — boolean// status.rectangle.currentCount — number// status.rectangle.maxCount — number | nullOr use the useConstraints hook for convenience:
import { useConstraints } from 'osdlabel/hooks';
const { isToolEnabled, canAddAnnotation } = useConstraints();
if (isToolEnabled('rectangle')) { // Rectangle tool is available}