The purpose of this hook is to provide functionality for editing features on the map, such as drawing polylines, polygons, markers, rectangles, circles, and more.
https://leaflet-editable-hook.vercel.app/
- leaflet: "^1.9.4"
- leaflet-editable: "^1.2.0"
- react: "^19.0.0"
- react-dom: "^19.0.0"
- react-leaflet: "^5.0.0"
Install with npm
npm i leaflet-editable-hookSee full documentation about Leaflet.Editable
| Hook returned methods | Returns | Description |
|---|---|---|
| drawing() | boolean | Return true if any drawing action is ongoing. |
| stopDrawing() | void | When you need to stop any ongoing drawing, without needing to know which editor is active. |
| commitDrawing() | void | When you need to commit any ongoing drawing, without needing to know which editor is active. |
| startPolyline(<L.LatLng> latlng, options) | L.Polyline | Start drawing a Polyline. If latlng is given, a first point will be added. In any case, continuing on user click. If options is given, it will be passed to the Polyline class constructor. |
| startPolygon(<L.LatLng> latlng, options) | L.Polygon | Start drawing a Polygon. If latlng is given, a first point will be added. In any case, continuing on user click. If options is given, it will be passed to the Polygon class constructor. |
| startMarker(<L.LatLng> latlng, options) | L.Marker | Start adding a Marker. If latlng is given, the Marker will be shown first at this point. In any case, it will follow the user mouse, and will have a final latlng on next click (or touch). If options is given, it will be passed to the Marker class constructor. |
| startRectangle(<L.LatLng> latlng, options) | L.Rectangle | Start drawing a Rectangle. If latlng is given, the Rectangle anchor will be added. In any case, continuing on user drag. If options is given, it will be passed to the Rectangle class constructor. |
| startCircle(<L.LatLng> latlng, options) | L.Circle | Start drawing a Circle. If latlng is given, the Circle anchor will be added. In any case, continuing on user drag. If options is given, it will be passed to the Circle class constructor. |
| enableEdit(feature: L.Layer) | void | Enable editing, by creating an editor if not existing, and then calling enable on it. |
| disableEdit(feature: L.Layer) | void | Disable editing, also remove the editor property reference. |
| Events |
|---|
| onCreated |
| onEnable |
| onDisable |
| onEditing |
| onDragStart |
| onDrag |
| onDragEnd |
| onDrawingStart |
| onDrawingEnd |
| onDrawingCancel |
| onDrawingCommit |
| onDrawingMousedown |
| onDrawingMouseup |
| onDrawingClick |
| onDrawingMove |
| onDrawingClicked |
| onVertexNew |
| onVertexClick |
| onVertexClicked |
| onVertexRawclick |
| onVertexDeleted |
| onVertexCtrlclick |
| onVertexShiftclick |
| onVertexMetakeyclick |
| onVertexAltclick |
| onVertexContextmenu |
| onVertexMousedown |
| onVertexDrag |
| onVertexDragstart |
| onVertexDragend |
| onMiddlemarkerMousedown |
| onShapeNew |
| onShapeDelete |
| onShapeDeleted |
import{useMap,Marker,Tooltip}from"react-leaflet";import{useState,useEffect}from"react";import*asturffrom"@turf/turf";import{useLeafletEditable}from"leaflet-editable-hook";functionRuler(){constmap=useMap();const[ruler,setRuler]=useState(null);constonDrawingClicked=(e)=>{constposition=e.latlng;constlatlngs=e.layer._latlngs;letlength=0;if(latlngs.length>1){constline=turf.lineString([
...latlngs.map((item)=>[item.lng,item.lat]),]);length=turf.length(line,{units: "kilometers"});}setRuler(<RulerMarkerposition={[position.lat,position.lng]}length={length}/>);};constonVertexDrag=(e)=>{constlatlngs=e.layer._latlngs;letlength=0;if(latlngs.length>1){constline=turf.lineString([
...latlngs.map((item)=>[item.lng,item.lat]),]);length=turf.length(line,{units: "kilometers"});}setRuler(<RulerMarkerposition={[latlngs[latlngs.length-1].lat,latlngs[latlngs.length-1].lng,]}length={length}/>);};const{ startPolyline }=useLeafletEditable({events: {
onDrawingClicked,
onVertexDrag,},});useEffect(()=>{constpolyline=startPolyline();return()=>{map.removeLayer(polyline);};},[]);returnruler;}functionRulerMarker({ position, length }){return(<Markerposition={position}icon={L.divIcon({html: `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill-opacity="0%"> <title>circle-small</title> <path d="M12,10A2,2 0 0,0 10,12C10,13.11 10.9,14 12,14C13.11,14 14,13.11 14,12A2,2 0 0,0 12,10Z" /> </svg>`,className: "marker-icon",iconSize: [24,24],popupAnchor: [0,-12],})}><Tooltippermanentoffset={[10,0]}direction="right">{length.toFixed(3)} KM
</Tooltip></Marker>);}exportdefaultRuler;Thanks goes to these wonderful people (emoji key):
Charles Richardson 💻 | saiNaruUFL 💻 | Alejandro Ramírez Muñoz 💻 |
This project follows the all-contributors specification. Contributions of any kind welcome!