Skip to content

Modes

LibreDraw uses a mode-based architecture. Only one mode is active at a time, and each mode defines how user interactions are interpreted.

Overview

ModeDescriptionActivated by
idleNo drawing interaction. Map behaves normally.Default / toolbar
draw-pointClick to place a point feature.Toolbar draw-point button / setMode('draw-point')
draw-lineClick to add vertices, double-click to finalize line.Toolbar draw-line button / setMode('draw-line')
drawClick to add vertices, double-click to close polygon.Toolbar draw button / setMode('draw')
selectClick to select, drag to edit vertices or move point/line/polygon.Toolbar select button / setMode('select')
splitSplit a polygon with a two-point line.Toolbar split button / setMode('split')
setbackApply inward edge setback with distance input.Toolbar setback button / setMode('setback')

Try it

Use the buttons below to switch between modes. Place points in draw-point mode, draw lines in draw-line mode, draw polygons in draw mode, then switch to select mode to edit them.

Idle Mode

The default mode. No drawing or editing interactions are active. The map behaves normally — pan, zoom, and all standard MapLibre interactions work.

ts
draw.setMode('idle');

Draw Point Mode

In draw-point mode, you place point features on the map. Each click/tap instantly creates a Point feature.

Mouse Interaction

ActionEffect
ClickPlace a point
Escape keyClear snap indicator

Touch Interaction

ActionEffect
TapPlace a point

Behavior

  • One click = one Point feature (instant creation, no multi-step workflow)
  • The mode stays active for continuous placement — you can place multiple points without switching modes
  • Snap to existing vertices is supported when enabled
  • Map panning remains enabled during draw-point mode
  • Double-click zoom is disabled to prevent accidental zoom
ts
draw.setMode('draw-point');

draw.on('create', (e) => {
  console.log('New point:', e.feature);
  // Remains in draw-point mode for continuous placement
});

Draw Line Mode

In draw-line mode, you create new LineString features by clicking on the map.

Mouse Interaction

ActionEffect
ClickAdd a vertex
Double-clickFinalize the line (minimum 2 vertices)
Escape keyCancel the current drawing

Touch Interaction

ActionEffect
TapAdd a vertex
Double-tapFinalize the line
Long-pressUndo last vertex

Behavior

  • A preview line follows the cursor while drawing
  • Unlike polygon drawing, the line is not closed — it remains an open path
  • Minimum 2 vertices are required to finalize
  • The mode stays active after finalization for continuous drawing
  • Snap to existing vertices and edges is supported when enabled
  • Map panning is disabled during draw-line mode to prevent accidental panning
  • Double-click zoom is disabled during draw-line mode
ts
draw.setMode('draw-line');

draw.on('create', (e) => {
  console.log('New line:', e.feature);
  // Remains in draw-line mode for continuous drawing
});

Draw Mode

In draw mode, you create new polygons by clicking on the map.

Mouse Interaction

ActionEffect
ClickAdd a vertex
Double-clickClose the polygon (minimum 3 vertices)
Escape keyCancel the current drawing

Touch Interaction

ActionEffect
TapAdd a vertex
Double-tapClose the polygon
Long-pressUndo last vertex

Behavior

  • A preview line follows the cursor while drawing
  • A semi-transparent polygon preview shows the current shape
  • Map panning is disabled during draw mode
  • Double-click zoom is disabled during draw mode
  • Self-intersecting polygons are automatically rejected
ts
draw.setMode('draw');

draw.on('create', (e) => {
  console.log('New polygon:', e.feature);
  // Remains in draw mode for continuous drawing
});

Select Mode

In select mode, you can select existing features (points, lines, and polygons) and edit them.

Selecting

ActionEffect
Click on polygonSelect it (shows vertex handles)
Click near lineSelect it (within 20px threshold, shows vertex handles)
Click near pointSelect it (within 20px threshold)
Click outsideDeselect
Delete keyDelete selected feature

Point Editing

When a point is selected:

ActionEffect
Drag the pointMove it to a new position

Line Editing

When a line is selected, vertex handles appear:

ActionEffect
Drag a vertexMove the vertex
Drag a midpointInsert a new vertex and drag it
Double-click a vertexDelete the vertex (minimum 2 maintained)
Drag near the lineMove the entire line

Vertex Editing

When a polygon is selected, vertex handles appear:

ActionEffect
Drag a vertexMove the vertex
Drag a midpointInsert a new vertex and drag it
Long-press a vertexDelete the vertex (minimum 3 maintained)

Polygon Dragging

ActionEffect
Drag inside polygonMove the entire polygon

Behavior

  • Double-click zoom is disabled during select mode
  • Map panning is temporarily disabled during vertex/polygon/line/point drag
  • Self-intersection is prevented during polygon editing (not enforced for lines)
  • Undo/redo works for all edit operations
ts
draw.setMode('select');

// Or programmatically select a feature
draw.selectFeature('feature-id');

draw.on('update', (e) => {
  console.log('Polygon edited:', e.feature);
});

draw.on('selectionchange', (e) => {
  console.log('Selection:', e.selectedIds);
});

Split Mode

In split mode, you split one polygon into two polygons.

ActionEffect
Click on polygonSelect split target
Click first pointSet split-line start
Click second pointExecute split
Escape keyCancel current split interaction
ts
draw.setMode('split');
draw.on('split', (e) => console.log(e.originalFeature.id, e.features));
draw.on('splitfailed', (e) => console.warn(e.reason));

Setback Mode

In setback mode, you select an edge and apply inward offset by distance.

ActionEffect
Click on polygonSelect setback target
Click edgeStart preview
Change distanceUpdate preview line
Enter / execute buttonApply setback
Escape keyCancel and reset
ts
draw.setMode('setback');
draw.on('setback', (e) => console.log(e.edgeIndex, e.distance));
draw.on('setbackfailed', (e) => console.warn(e.reason));

Mode Transitions

                setMode('draw-point')
           ┌─────────────────────────┐
           │                         ▼
           │                   ┌────────────┐
           │                   │ draw-point │
           │                   └────────────┘
           │                         │
           ├─────────────────────────┘
           │   setMode('draw-line')
           ├─────────────────────────┐
           │                         ▼
           │                   ┌────────────┐
           │                   │ draw-line  │
           │                   └────────────┘
           │                         │
           ├─────────────────────────┘
           │    setMode('draw')
           ├─────────────────────────┐
           │                         ▼
        ┌──────┐               ┌──────────┐
        │ idle │               │   draw   │
        └──────┘               └──────────┘
           ▲                         │
           │     polygon created     │
           └─────────────────────────┘

           │    setMode('select')
           ├─────────────────────────┐
           │                         ▼
           │                   ┌──────────┐
           │                   │  select  │
           │                   └──────────┘
           │                         │
           ├─────────────────────────┘
           │    setMode('split')
           ├─────────────────────────┐
           │                         ▼
           │                   ┌──────────┐
           │                   │  split   │
           │                   └──────────┘
           │                         │
           ├─────────────────────────┘
           │    setMode('setback')
           ├─────────────────────────┐
           │                         ▼
           │                   ┌──────────┐
           │                   │ setback  │
           │                   └──────────┘
           │                         │
           └─────────────────────────┘
                  setMode('idle')

Every mode transition emits a modechange event:

ts
draw.on('modechange', (e) => {
  console.log(`${e.previousMode} → ${e.mode}`);
});

Released under the MIT License.