react-map-gl-draw
is a react based drawing library tailored for react-map-gl
.
mode
(Object, Optional) - A mode instance. default to null. Support the following modes from @nebula.gl/edit-modes
. Note: Currently react-map-gl-draw
does not support modeConfig
in @nebula.gl/edit-modes
.
DrawCircleByDiameterMode
: Lets you draw a GeoJson Circle
feature.DrawCircleFromCenterMode
: Lets you draw a GeoJson Circle
feature.DrawPointMode
: Lets you draw a GeoJson Point
feature.DrawLineStringMode
: Lets you draw a GeoJson LineString
feature.DrawPolygonMode
: Lets you draw a GeoJson Polygon
feature.DrawRectangleMode
: Lets you draw a Rectangle
(represented as GeoJson Polygon
feature) with two clicks - start drawing on first click, and finish drawing on second click.
modeConfig: {dragToDraw: true}
. See modeConfig
for more details.And an advanced
EditingMode
: Lets you select and drag vertices; and drag features.modeConfig
(Object, Optional) - Additional configuration for the provided mode.
Check nebula.gl
doc to see mode details. features
(Feature[], Optional) - List of features in GeoJson format. If features
are provided from users, then react-map-gl-draw
respect the users' input, and therefore ignore any internal features
. But if features
are not provided, then react-map-gl-draw
manages features
internally, and users can access and manipulate the features by calling getFeatures
, addFeatures
, and deleteFeatures
.selectedFeatureIndex
(String, Optional) - Index of the selected feature.clickRadius
(Number, Optional) - Radius to detect features around a hovered or clicked point. Default value is 0
onSelect
(Function, Optional) - callback when clicking a position when selectable
set to true. Receives an object containing the following parameters
selectedFeature
: selected feature. null
if clicked an empty space.selectedFeatureIndex
: selected feature index.null
if clicked an empty space.editHandleIndex
: selected editHandle index. null
if clicked an empty space.screenCoords
: screen coordinates of the clicked position.mapCoords
: map coordinates of the clicked position.onUpdate
(Function, Optional) - callback when any feature is updated. Receives an object containing the following parameters
data
(Feature[]) - the updated list of GeoJSON features.editType
(String) - addFeature
, addPosition
, finishMovePosition
editContext
(Array) - list of edit objects, depend on editType
, each object may contain featureIndexes
, editHandleIndexes
, screenCoords
, mapCoords
.Feature object structure:
{
id, // an unique identified generated inside react-map-gl-draw library
geometry: {
coordinates, // latitude longitude pairs of the geometry points
type // geojson type, one of `Point`, `LineString`, or `Polygon`
},
properties: {
renderType, // Mainly used for styling, one of `Point`, `LineString`, `Polygon`, or `Rectangle`. Different from `geometry.type`. i.e. a rectangle's renderType is `Rectangle`, and `geometry.type` is `Polygon`. An incomplete (not closed) Polygon's renderType is `Polygon`, `geometry.type` is `LineString`
...otherProps // other properties user passed in
}
}
featureStyle
(Object|Function, Optional) : Object - Either a style objects or a function to style a feature, function parameters are
feature
: feature to style.index
: index of the feature.state
: one of SELECTED
, HOVERED
, INACTIVE
, UNCOMMITTED
, CLOSING
.Returns is a map of style objects passed to SVG path
elements.
featureShape
(String|Function, Optional): if is a string, should be one of rect
or circle
. If is a function, will receive the following parameters
feature
: feature to style.index
: index of the feature.state
: one of SELECTED
, HOVERED
, INACTIVE
, UNCOMMITTED
, CLOSING
.editHandleStyle
(Object|Function, Optional) : Object - Either a style objects or a function to style an editHandle
, function parameters are
feature
: feature to style.index
: index of the editHandle vertex in the feature.state
: one of SELECTED
, HOVERED
, INACTIVE
, UNCOMMITTED
, CLOSING
.shape
: shape resolved from editHandleShape
.Returns is a map of style objects passed to SVG circle
or rect
elements.
editHandleShape
(String|Function, Optional): if is a string, should be one of rect
or circle
. If is a function, will receive the following parameters
feature
: feature to style.index
: index of the editHandle vertex in the feature.state
: one of SELECTED
, HOVERED
, INACTIVE
, UNCOMMITTED
, CLOSING
.Feature
: any drawn shape, one of point, line, polygon or rectangle.EditHandle
: vertex of the feature being edited.INACTIVE
: neither selected nor hovered, default state of a complete feature
or editHandle
.SELECTED
: being clicked or dragged.HOVERED
: hovered over by the mouse pointer.UNCOMMITTED
: in the middle of drawing, not yet added to the feature being edited.CLOSING
: closing a polygon.state
:As shown in the above image, for the feature currently being edited,
featureStyle({feature, state: SELECTED})
will be applied to the committed parts of the feature. (Green strokes)editHandleStyle({state: SELECTED})
will be applied to the committed editHandle vertices. (Vertices with black stroke)featureStyle({feature, state: UNCOMMITTED})
will be applied to the uncommitted parts of the feature. (Gray stroke)editHandleStyle({state: UNCOMMITTED})
will be applied to the uncommitted editHandle vertex. (Gray vertex)getFeatures
addFeatures
(Feature | Feature[])deleteFeatures
(Feature | Feature[])@turf/difference
: If you are seeing the below error, you can force @turf/difference
's version in your project package.json
file and redo yarn install
. ./node_modules/@turf/difference/index.mjs Can't import the named export 'diff' from non EcmaScript module (only default export is available)
{
...,
"dependencies": {
...
},
"resolutions": {
"@turf/difference": "6.0.1"
}
}
references:
@turf/difference
issueBasic example: Draw polygon
import * as React from 'react';
import MapGL from 'react-map-gl';
import {
Editor,
DrawPolygonMode,
} from 'react-map-gl-draw';
const DEFAULT_VIEWPORT = {
width: 800,
height: 600,
longitude: -122.45,
latitude: 37.78,
zoom: 14,
};
class App extends Component {
constructor(props) {
super(props);
this.state = {
viewport: DEFAULT_VIEWPORT,
modeHandler: null,
};
}
_updateViewport = (viewport) => {
this.setState({ viewport });
};
render() {
const { viewport } = this.state;
return (
<MapGL
{...viewport}
width="100%"
height="100%"
mapStyle={'mapbox://styles/mapbox/light-v9'}
onViewportChange={this._updateViewport}
>
<Editor
// to make the lines/vertices easier to interact with
clickRadius={12}
mode={new DrawPolygonMode()}
/>
{this._renderToolbar()}
</MapGL>
);
}
}
Add customized styles
This is continuous example extends from the Basic Example
. Check default style used in editor for more details.
<Editor
// to make the lines/vertices easier to interact with
clickRadius={12}
mode={new DrawPolygonMode()}
featureStyle={({feature, state}) => {
if (state === RENDER_STATE.SELECTED) {
return {
stroke: 'rgb(38, 181, 242)',
fill: 'rgb(189,189,189)'
}
}
return {
stroke: 'rgb(189,189,189)',
strokeDasharray: '4,2',
};
}}
editHandleStyle={({feature, shape, state}) => {
if (state === RENDER_STATE.SELECTED) {
return {
stroke: 'rgb(38, 181, 242)',
fill: 'rgb(189,189,189)'
}
}
return {
stroke: 'rgb(189,189,189)',
strokeDasharray: '4,2',
};
}}
editHandleShape={'circle'}
/>
Advanced example: multiple draw modes and editing drawn features
import React, { Component } from 'react';
import MapGL from 'react-map-gl';
import {
Editor,
EditingMode,
DrawLineStringMode,
DrawPolygonMode,
} from 'react-map-gl-draw';
const MODES = [
{ id: 'drawPolyline', text: 'Draw Polyline', handler: DrawLineStringMode },
{ id: 'drawPolygon', text: 'Draw Polygon', handler: DrawPolygonMode },
{ id: 'editing', text: 'Edit Feature', handler: EditingMode },
];
const DEFAULT_VIEWPORT = {
width: 800,
height: 600,
longitude: -122.45,
latitude: 37.78,
zoom: 14,
};
class App extends Component {
constructor(props) {
super(props);
this.state = {
viewport: DEFAULT_VIEWPORT,
modeId: null,
modeHandler: null,
};
}
_switchMode = evt => {
const modeId = evt.target.value === this.state.modeId ? null : evt.target.value;
const mode = MODES.find(m => m.id === modeId);
const modeHandler = mode ? new mode.handler() : null;
this.setState({modeId, modeHandler});
};
_renderToolbar = () => {
return (
<div style={{position: 'absolute', top: 0, right: 0, maxWidth: '320px'}}>
<select onChange={this._switchMode}>
<option value="">--Please choose a draw mode--</option>
{MODES.map(mode => <option key={mode.id} value={mode.id}>{mode.text}</option>)}
</select>
</div>
);
};
_updateViewport = (viewport) => {
this.setState({ viewport });
};
render() {
const { viewport, modeHandler } = this.state;
return (
<MapGL
{...viewport}
width="100%"
height="100%"
mapStyle={'mapbox://styles/mapbox/light-v9'}
onViewportChange={this._updateViewport}
>
<Editor
// to make the lines/vertices easier to interact with
clickRadius={12}
mode={modeHandler}
/>
{this._renderToolbar()}
</MapGL>
);
}
}