By Tissue Type
- “Tumor”
- “Stroma”
- “Necrosis”
- “Normal”
Annota’s layer system allows you to organize annotations into logical groups with independent styling and visibility control.
Use the useLayerManager hook to create and manage layers:
import { useLayerManager } from 'annota';
function LayerPanel() { const layerManager = useLayerManager();
const handleCreateLayer = () => { layerManager.createLayer({ id: 'tumor', name: 'Tumor Regions', visible: true, style: { fill: 'rgba(255, 0, 0, 0.3)', stroke: '#ff0000', strokeWidth: 2, }, }); };
return ( <button onClick={handleCreateLayer}> Create Tumor Layer </button> );}Each layer has the following properties:
| Property | Type | Description |
|---|---|---|
id | string | Unique identifier for the layer |
name | string | Display name for the layer |
visible | boolean | Whether annotations in this layer are visible |
opacity | number | Layer transparency (0-1) |
locked | boolean | Prevent editing of annotations |
style | AnnotationStyle | Default style for annotations in this layer |
Annotations can be assigned to layers via their properties.layer field:
const annotation = { id: 'ann-1', shape: { type: 'rectangle', geometry: { x: 100, y: 100, width: 200, height: 150 }, }, properties: { layer: 'tumor', // Assign to tumor layer },};Or when using tools:
const polygonTool = new PolygonTool({ layer: 'tumor', // All annotations created will be assigned to this layer});Toggle layer visibility to show/hide all annotations in a layer:
function LayerList() { const layerManager = useLayerManager();
return ( <div> {layerManager.layers.map(layer => ( <div key={layer.id}> <input type="checkbox" checked={layer.visible} onChange={(e) => layerManager.updateLayer(layer.id, { visible: e.target.checked, }) } /> {layer.name} </div> ))} </div> );}Layers define default styles for their annotations. Individual annotations can override:
// Layer style (default for all annotations in layer)const layerStyle = { fill: 'rgba(255, 0, 0, 0.3)', stroke: '#ff0000', strokeWidth: 2,};
// Annotation-specific style overrideconst annotation = { id: 'special-1', properties: { layer: 'tumor' }, style: { fill: 'rgba(255, 255, 0, 0.5)', // Override fill color },};Delete a layer and optionally remove all its annotations:
// Delete layer and keep annotations (they become unassigned)layerManager.deleteLayer('tumor', false);
// Delete layer and remove all its annotationslayerManager.deleteLayer('tumor', true);By Tissue Type
By Annotator
By Status
By Source
import { useLayerManager, useLayers } from 'annota';import { useState } from 'react';
function LayerPanel() { const layerManager = useLayerManager(); const layers = useLayers(); const [newLayerName, setNewLayerName] = useState('');
const createLayer = () => { if (!newLayerName) return;
layerManager.createLayer({ id: newLayerName.toLowerCase().replace(/\s+/g, '-'), name: newLayerName, visible: true, style: { fill: `rgba(${Math.random() * 255}, ${Math.random() * 255}, ${Math.random() * 255}, 0.3)`, stroke: '#000000', strokeWidth: 2, }, }); setNewLayerName(''); };
return ( <div className="layer-panel"> <h3>Layers</h3>
<div className="create-layer"> <input value={newLayerName} onChange={(e) => setNewLayerName(e.target.value)} placeholder="Layer name" /> <button onClick={createLayer}>Add</button> </div>
<ul> {layers.map(layer => ( <li key={layer.id}> <input type="checkbox" checked={layer.visible} onChange={(e) => layerManager.updateLayer(layer.id, { visible: e.target.checked }) } /> <span>{layer.name}</span> <button onClick={() => layerManager.deleteLayer(layer.id, true)}> Delete </button> </li> ))} </ul> </div> );}