Drawing Controller & Interactive Shapes
The DrawingController class provides an interface for drawing polygons, circles, and text
notations directly on the map viewport.
DrawingController and the drawing modes live under @sovereignsolutions/ss-map-gl/drawing, not
the package root, so apps that never draw don't pay for the drawing engine in their bundle.
Initializing DrawingController
import { DrawingController } from '@sovereignsolutions/ss-map-gl/drawing';
const drawingController = new DrawingController(mapEngine, {
showToolbar: true,
onDrawComplete: (features) => console.log('Drawing finished:', features),
onShapeSelect: (features) => console.log('Selected:', features),
onShapeUpdate: (features) => console.log('Updated:', features),
onShapeDelete: (features) => console.log('Deleted:', features),
});
DrawingController accepts either a MapEngine or a map created directly by another tool (for
example react-map-gl or vue-maplibre-gl) - no change needed if you were already passing a
MapEngine.
Supported Drawing Modes
You can trigger drawing modes programmatically via drawingController.setMode(mode):
| Mode | Description |
|---|---|
'polygon' | Click to place vertices, double-click to close the shape |
'circle' | Click to set center, drag to define radius |
'notation' | Click on the map to place a text label anchor point |
'select' | Select, move, and edit existing shapes |
'trash' | Delete the currently selected feature |
Text Notation
When notation mode is active, clicking the map places a point feature. An editor popup
automatically opens allowing the user to configure the text content, font size (12px to 32px),
and color (preset palette or custom hex picker). Text notations are exported as GeoJSON Point
features with isNotation: true in properties - see
GeoJSON Import & Export.
DrawingController Public API
| Method | Signature | Description |
|---|---|---|
setMode | (mode: 'polygon' | 'circle' | 'notation' | 'select' | 'trash') => void | Activate a drawing or editing mode |
getAllFeatures | () => FeatureCollection | Get all drawn features as a GeoJSON FeatureCollection |
addFeatures | (features: FeatureCollection) => void | Load GeoJSON features onto the drawing canvas |
deleteFeature | (id: string) => void | Remove a specific feature by ID |
clear | () => void | Remove all features from the drawing canvas |
destroy | () => void | Cleanup all event listeners, popups, toolbar, and remove the draw control |
draw (field) | MapboxDraw | Direct access to the underlying MapboxDraw instance for advanced use |
Event Contract & Lifecycle Hooks
The SDK provides direct callback event interfaces for all drawing interactions and map viewport lifecycle changes. Source: Event Contract & Lifecycle Hooks in the SDK README.
| Callback Hook | Event Type | Description | Argument Signature |
|---|---|---|---|
onDrawStart | Drawing Mode | User entered a drawing state | (mode: string) => void |
onDrawComplete | Draw Complete | Shape finished drawing and added to map | (features: Feature[]) => void |
onDrawCreate | Draw Create | Raw draw.create event (all shape types) | (features: Feature[]) => void |
onDrawUpdate | Draw Update | Raw draw.update event | (features: Feature[]) => void |
onDrawDelete | Draw Delete | Raw draw.delete event | (features: Feature[]) => void |
onShapeSelect | Shape Select | User clicked/selected a shape on map | (features: Feature[]) => void |
onShapeUpdate | Shape Update | Shape vertex dragged, circle resized, or moved | (features: Feature[]) => void |
onShapeDelete | Shape Delete | User deleted a shape from the map | (features: Feature[]) => void |
onModeChange | Mode Change | SDK changed drawing mode internally (e.g. after shape completes) | (mode: string) => void |
onDrag | Viewport Hook (MapEngine) | Map viewport was panned/dragged | () => void |
onZoom | Viewport Hook (MapEngine) | Map viewport was zoomed | () => void |
onBoundsChange | Viewport Hook (MapEngine) | Viewport bounds changed (at end of pan/zoom) | (bounds: ViewportBounds) => void |
drawingController.onDrawStart = (mode: string) => {
console.log('User started drawing in mode:', mode);
};
drawingController.onDrawComplete = (features) => {
console.log('New shape created:', features);
};
drawingController.onShapeUpdate = (features) => {
console.log('Shape vertices updated:', features);
};
drawingController.onShapeDelete = (features) => {
console.log('Shape removed:', features);
};
Cleanup & Unmount
Invoke destroy() to remove layers, markers, listeners, controls, and DOM elements. Source:
Cleanup & Unmount Behavior in the SDK README.
// Unmount Drawing Controller and toolbar
drawingController.destroy();
// Terminate the map instance
mapEngine.destroy();
Known Limitations
- Circle approximation: circles are represented as 64-vertex polygons. Resizing works smoothly, but fine coordinate precision is subject to 64-segment resolution.
- Global cursor style conflicts: when switching modes, the underlying draw library alters CSS pointer styles. Hover interactions on clusters can overlay standard pointer rules.
- Text notation rendering: notation labels are rendered using MapLibre
symbollayers. Label visibility at very small zoom levels depends on the active base map style's collision detection settings.
See also: GeoJSON Import & Export.