React-Leaflet Draw Controls

0.21.0 · active · verified Tue Apr 21

react-leaflet-draw provides a React component, `EditControl`, that integrates the popular Leaflet.draw plugin into React-Leaflet applications. It allows users to add drawing and editing capabilities for geographic features (polygons, lines, circles, markers) directly on a Leaflet map. The current stable version is 0.21.0. While there isn't a stated release cadence, development appears active, aligning with updates to its peer dependencies like `react-leaflet`. Its key differentiator is providing a declarative React interface for Leaflet.draw's imperative API, simplifying state management and rendering for interactive map editing within a React ecosystem. It relies heavily on `react-leaflet`'s context system to access the underlying Leaflet map instance. The library focuses solely on the draw functionality rather than broader GIS features.

Common errors

Warnings

Install

Imports

Quickstart

This example demonstrates how to set up a basic Leaflet map with drawing and editing capabilities using `react-leaflet-draw`. It includes importing necessary components and styles, handling common Leaflet icon issues, and setting up event handlers for creation, editing, and deletion of map features. It also shows how to customize the available drawing tools and editing options.

import { MapContainer, TileLayer, FeatureGroup, Circle } from 'react-leaflet';
import { EditControl } from "react-leaflet-draw";
import 'leaflet/dist/leaflet.css';
import 'leaflet-draw/dist/leaflet.draw.css';

// Workaround for missing Leaflet icons in Webpack/Vite
import L from 'leaflet';
delete L.Icon.Default.prototype._getIconUrl;
L.Icon.Default.mergeOptions({
  iconRetinaUrl: 'https://unpkg.com/leaflet@1.7.1/dist/images/marker-icon-2x.png',
  iconUrl: 'https://unpkg.com/leaflet@1.7.1/dist/images/marker-icon.png',
  shadowUrl: 'https://unpkg.com/leaflet@1.7.1/dist/images/marker-shadow.png'
});

const MapWithDrawControls = () => {
  const _onEdited = (e) => {
    e.layers.eachLayer((layer) => {
      console.log('Layer edited:', layer.toGeoJSON());
    });
  };

  const _onCreated = (e) => {
    const { layerType, layer } = e;
    console.log('Layer created:', layerType, layer.toGeoJSON());
  };

  const _onDeleted = (e) => {
    e.layers.eachLayer((layer) => {
      console.log('Layer deleted:', layer.toGeoJSON());
    });
  };

  return (
    <MapContainer center={[51.505, -0.09]} zoom={13} style={{ height: '500px', width: '100%' }}>
      <TileLayer
        attribution='&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
        url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
      />
      <FeatureGroup>
        <EditControl
          position='topright'
          onEdited={_onEdited}
          onCreated={_onCreated}
          onDeleted={_onDeleted}
          draw={{
            rectangle: false, // Disable rectangle drawing
            circlemarker: false // Disable circle marker drawing
          }}
          edit={{
            poly: { allowIntersection: false }, // Prevent self-intersections for polygons
            featureGroup: null // This ensures only items in the parent FeatureGroup are editable
          }}
        />
        <Circle center={[51.51, -0.06]} radius={200} />
      </FeatureGroup>
    </MapContainer>
  );
};

export default MapWithDrawControls;

view raw JSON →