leaflet-polydraw 0.8.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENCE +21 -0
- package/README.md +1006 -0
- package/dist/icons/icon-activate.svg +1 -0
- package/dist/icons/icon-add-elbow.svg +128 -0
- package/dist/icons/icon-bbox.svg +47 -0
- package/dist/icons/icon-bezier.svg +132 -0
- package/dist/icons/icon-draw.svg +1 -0
- package/dist/icons/icon-erase.svg +3 -0
- package/dist/icons/icon-info-white.svg +25 -0
- package/dist/icons/icon-settings-white.svg +15 -0
- package/dist/icons/icon-simplify.svg +61 -0
- package/dist/icons/icon-simplify2.svg +46 -0
- package/dist/icons/icon-subtract.svg +1 -0
- package/dist/icons/icon-trash-hover-white.svg +16 -0
- package/dist/icons/icon-trash-white.svg +16 -0
- package/dist/leaflet-polydraw.css +1 -0
- package/dist/polydraw.es.js +20688 -0
- package/dist/polydraw.es.js.map +1 -0
- package/dist/polydraw.umd.min.js +2 -0
- package/dist/polydraw.umd.min.js.map +1 -0
- package/dist/styles/polydraw.css +419 -0
- package/dist/types/buttons.d.ts +14 -0
- package/dist/types/buttons.d.ts.map +1 -0
- package/dist/types/coordinate-utils.d.ts +21 -0
- package/dist/types/coordinate-utils.d.ts.map +1 -0
- package/dist/types/enums.d.ts +27 -0
- package/dist/types/enums.d.ts.map +1 -0
- package/dist/types/geometry-utils.d.ts +24 -0
- package/dist/types/geometry-utils.d.ts.map +1 -0
- package/dist/types/icon-factory.d.ts +13 -0
- package/dist/types/icon-factory.d.ts.map +1 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/managers/mode-manager.d.ts +91 -0
- package/dist/types/managers/mode-manager.d.ts.map +1 -0
- package/dist/types/managers/polygon-draw-manager.d.ts +88 -0
- package/dist/types/managers/polygon-draw-manager.d.ts.map +1 -0
- package/dist/types/managers/polygon-geometry-manager.d.ts +75 -0
- package/dist/types/managers/polygon-geometry-manager.d.ts.map +1 -0
- package/dist/types/managers/polygon-interaction-manager.d.ts +116 -0
- package/dist/types/managers/polygon-interaction-manager.d.ts.map +1 -0
- package/dist/types/managers/polygon-mutation-manager.d.ts +163 -0
- package/dist/types/managers/polygon-mutation-manager.d.ts.map +1 -0
- package/dist/types/map-state.d.ts +22 -0
- package/dist/types/map-state.d.ts.map +1 -0
- package/dist/types/polydraw.d.ts +87 -0
- package/dist/types/polydraw.d.ts.map +1 -0
- package/dist/types/polygon-helpers.d.ts +35 -0
- package/dist/types/polygon-helpers.d.ts.map +1 -0
- package/dist/types/polygon-information.service.d.ts +27 -0
- package/dist/types/polygon-information.service.d.ts.map +1 -0
- package/dist/types/polygon.util.d.ts +32 -0
- package/dist/types/polygon.util.d.ts.map +1 -0
- package/dist/types/turf-helper.d.ts +141 -0
- package/dist/types/turf-helper.d.ts.map +1 -0
- package/dist/types/types/polydraw-interfaces.d.ts +351 -0
- package/dist/types/types/polydraw-interfaces.d.ts.map +1 -0
- package/dist/types/utils.d.ts +57 -0
- package/dist/types/utils.d.ts.map +1 -0
- package/package.json +79 -0
package/README.md
ADDED
|
@@ -0,0 +1,1006 @@
|
|
|
1
|
+
[](https://github.com/AndreasOlausson/leaflet-polydraw)
|
|
2
|
+
|
|
3
|
+
# Leaflet Polydraw
|
|
4
|
+
|
|
5
|
+
> **Advanced Leaflet plugin for interactive polygon drawing with point-to-point creation, smart merging, and comprehensive editing tools**
|
|
6
|
+
|
|
7
|
+
Leaflet Polydraw is a powerful, feature-rich plugin that transforms your Leaflet maps into interactive polygon drawing and editing environments. With intelligent merging, drag-and-drop functionality, and comprehensive editing tools, it's perfect for GIS applications, mapping tools, and spatial data collection.
|
|
8
|
+
|
|
9
|
+
[](https://badge.fury.io/js/leaflet-polydraw)
|
|
10
|
+
[](https://opensource.org/licenses/MIT)
|
|
11
|
+
[](https://www.typescriptlang.org/)
|
|
12
|
+
[](https://github.com/AndreasOlausson/leaflet-polydraw/actions/workflows/ci.yml)
|
|
13
|
+
|
|
14
|
+
## Key Features
|
|
15
|
+
|
|
16
|
+
[](https://raw.githubusercontent.com/AndreasOlausson/leaflet-polydraw/main/Leaflet.Polydraw/docs/images/feature-overview.png)
|
|
17
|
+
|
|
18
|
+
- **Point-to-Point Drawing**: Precise polygon creation with click-by-click vertex placement
|
|
19
|
+
- **Smart Polygon Merging**: Automatic detection and merging of overlapping polygons (including C-to-O shape completion)
|
|
20
|
+
- **Drag & Drop**: Intuitive polygon repositioning with intelligent spatial interactions
|
|
21
|
+
- **Advanced Editing**: Drag vertices, add/remove points, and reshape polygons
|
|
22
|
+
- **Smart Markers**: Intelligent marker separation prevents overlapping on small polygons
|
|
23
|
+
- **Hole Support**: Create complex polygons with holes and nested shapes
|
|
24
|
+
- **Performance Optimized**: Efficient rendering and interaction handling
|
|
25
|
+
- **Well Tested**: Comprehensive test suite with 167+ passing tests
|
|
26
|
+
- **TypeScript Ready**: Full TypeScript support with type definitions
|
|
27
|
+
|
|
28
|
+
## Table of Contents
|
|
29
|
+
|
|
30
|
+
1. [Installation](#installation)
|
|
31
|
+
2. [Quick Start](#quick-start)
|
|
32
|
+
3. [Configuration](#configuration)
|
|
33
|
+
4. [Features](#features)
|
|
34
|
+
5. [API Reference](#api-reference)
|
|
35
|
+
6. [Markers](#markers)
|
|
36
|
+
7. [Events](#events)
|
|
37
|
+
8. [Examples](#examples)
|
|
38
|
+
9. [Browser Support](#browser-support)
|
|
39
|
+
10. [Contributing](#contributing)
|
|
40
|
+
|
|
41
|
+
## Installation
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
npm install leaflet-polydraw
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## CDN Usage
|
|
48
|
+
|
|
49
|
+
You can also use Leaflet.Polydraw directly in the browser via a CDN like [jsDelivr](https://www.jsdelivr.com/) or [unpkg](https://unpkg.com/):
|
|
50
|
+
|
|
51
|
+
### Include via CDN
|
|
52
|
+
|
|
53
|
+
```html
|
|
54
|
+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/leaflet@1.9.4/dist/leaflet.css" />
|
|
55
|
+
<link
|
|
56
|
+
rel="stylesheet"
|
|
57
|
+
href="https://cdn.jsdelivr.net/npm/leaflet.polydraw@0.8.0/dist/styles/polydraw.css"
|
|
58
|
+
/>
|
|
59
|
+
<script src="https://cdn.jsdelivr.net/npm/leaflet@1.9.4/dist/leaflet.js"></script>
|
|
60
|
+
<script src="https://cdn.jsdelivr.net/npm/leaflet.polydraw@0.8.0/dist/polydraw.umd.min.js"></script>
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### Example Usage
|
|
64
|
+
|
|
65
|
+
```html
|
|
66
|
+
<script>
|
|
67
|
+
const map = L.map('map').setView([58.4, 15.6], 10);
|
|
68
|
+
L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
|
69
|
+
attribution: '© OpenStreetMap contributors',
|
|
70
|
+
}).addTo(map);
|
|
71
|
+
|
|
72
|
+
const polydraw = new LeafletPolydraw();
|
|
73
|
+
map.addControl(polydraw);
|
|
74
|
+
</script>
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
> Note: All icons and styles are included automatically when using the CSS from the CDN.
|
|
78
|
+
|
|
79
|
+
## Quick Start
|
|
80
|
+
|
|
81
|
+
### Basic Usage
|
|
82
|
+
|
|
83
|
+
```javascript
|
|
84
|
+
import * as L from 'leaflet';
|
|
85
|
+
import Polydraw from 'leaflet-polydraw';
|
|
86
|
+
|
|
87
|
+
// Create your map
|
|
88
|
+
const map = L.map('map').setView([58.402514, 15.606188], 10);
|
|
89
|
+
L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
|
90
|
+
attribution:
|
|
91
|
+
'© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors',
|
|
92
|
+
}).addTo(map);
|
|
93
|
+
|
|
94
|
+
// Add the PolyDraw control (includes all drawing buttons)
|
|
95
|
+
const polydraw = new Polydraw();
|
|
96
|
+
polydraw.addTo(map);
|
|
97
|
+
|
|
98
|
+
// Optionally add some predefined polygons
|
|
99
|
+
const octagon = [
|
|
100
|
+
[
|
|
101
|
+
[
|
|
102
|
+
L.latLng(58.404493, 15.6),
|
|
103
|
+
L.latLng(58.402928, 15.602928),
|
|
104
|
+
L.latLng(58.4, 15.604493),
|
|
105
|
+
L.latLng(58.397072, 15.602928),
|
|
106
|
+
L.latLng(58.395507, 15.6),
|
|
107
|
+
L.latLng(58.397072, 15.597072),
|
|
108
|
+
L.latLng(58.4, 15.595507),
|
|
109
|
+
L.latLng(58.402928, 15.597072),
|
|
110
|
+
L.latLng(58.404493, 15.6),
|
|
111
|
+
],
|
|
112
|
+
],
|
|
113
|
+
];
|
|
114
|
+
|
|
115
|
+
polydraw.addPredefinedPolygon(octagon);
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### Advanced Configuration
|
|
119
|
+
|
|
120
|
+
```javascript
|
|
121
|
+
import Polydraw from 'leaflet-polydraw';
|
|
122
|
+
|
|
123
|
+
const polyDrawControl = L.control
|
|
124
|
+
.polydraw({
|
|
125
|
+
position: 'topright',
|
|
126
|
+
config: {
|
|
127
|
+
touchSupport: true,
|
|
128
|
+
mergePolygons: true,
|
|
129
|
+
modes: {
|
|
130
|
+
dragPolygons: true,
|
|
131
|
+
attachElbow: true,
|
|
132
|
+
dragElbow: true,
|
|
133
|
+
},
|
|
134
|
+
dragPolygons: {
|
|
135
|
+
autoMergeOnIntersect: true,
|
|
136
|
+
autoHoleOnContained: true,
|
|
137
|
+
markerBehavior: 'hide',
|
|
138
|
+
},
|
|
139
|
+
markers: {
|
|
140
|
+
deleteMarker: true,
|
|
141
|
+
infoMarker: true,
|
|
142
|
+
menuMarker: true,
|
|
143
|
+
markerDeleteIcon: {
|
|
144
|
+
position: 5, // North
|
|
145
|
+
},
|
|
146
|
+
markerInfoIcon: {
|
|
147
|
+
position: 4, // NorthEast
|
|
148
|
+
useMetrics: true,
|
|
149
|
+
},
|
|
150
|
+
},
|
|
151
|
+
polygonOptions: {
|
|
152
|
+
color: '#ff0000',
|
|
153
|
+
fillColor: '#ff0000',
|
|
154
|
+
fillOpacity: 0.3,
|
|
155
|
+
},
|
|
156
|
+
},
|
|
157
|
+
})
|
|
158
|
+
.addTo(map);
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
## Configuration
|
|
162
|
+
|
|
163
|
+
### Default Configuration
|
|
164
|
+
|
|
165
|
+
```javascript
|
|
166
|
+
{
|
|
167
|
+
"touchSupport": true,
|
|
168
|
+
"mergePolygons": true,
|
|
169
|
+
"kinks": false,
|
|
170
|
+
"modes": {
|
|
171
|
+
"draw": true,
|
|
172
|
+
"subtract": true,
|
|
173
|
+
"deleteAll": true,
|
|
174
|
+
"p2p": true,
|
|
175
|
+
"attachElbow": true,
|
|
176
|
+
"dragElbow": true,
|
|
177
|
+
"dragPolygons": true,
|
|
178
|
+
"edgeDeletion": true
|
|
179
|
+
},
|
|
180
|
+
"dragPolygons": {
|
|
181
|
+
"realTimeUpdate": false,
|
|
182
|
+
"showDragHandle": false,
|
|
183
|
+
"opacity": 0.7,
|
|
184
|
+
"dragCursor": "move",
|
|
185
|
+
"hoverCursor": "grab",
|
|
186
|
+
"markerBehavior": "hide",
|
|
187
|
+
"markerAnimationDuration": 200,
|
|
188
|
+
"autoMergeOnIntersect": true,
|
|
189
|
+
"autoHoleOnContained": false,
|
|
190
|
+
"dragInteractionBehavior": "auto",
|
|
191
|
+
"modifierSubtract": {
|
|
192
|
+
"enabled": true,
|
|
193
|
+
"keys": {
|
|
194
|
+
"windows": "ctrlKey",
|
|
195
|
+
"mac": "metaKey",
|
|
196
|
+
"linux": "ctrlKey"
|
|
197
|
+
},
|
|
198
|
+
"subtractColor": "#D9460F",
|
|
199
|
+
"hideMarkersOnDrag": true
|
|
200
|
+
}
|
|
201
|
+
},
|
|
202
|
+
"edgeDeletion": {
|
|
203
|
+
"enabled": true,
|
|
204
|
+
"modifierKey": "auto",
|
|
205
|
+
"hoverColor": "#D9460F",
|
|
206
|
+
"confirmDeletion": false,
|
|
207
|
+
"minVertices": 3
|
|
208
|
+
},
|
|
209
|
+
"markers": {
|
|
210
|
+
"deleteMarker": true,
|
|
211
|
+
"infoMarker": true,
|
|
212
|
+
"menuMarker": true,
|
|
213
|
+
"coordsTitle": true,
|
|
214
|
+
"zIndexOffset": 0,
|
|
215
|
+
"markerIcon": {
|
|
216
|
+
"styleClasses": ["polygon-marker"],
|
|
217
|
+
"zIndexOffset": null
|
|
218
|
+
},
|
|
219
|
+
"holeIcon": {
|
|
220
|
+
"styleClasses": ["polygon-marker", "hole"],
|
|
221
|
+
"zIndexOffset": null
|
|
222
|
+
},
|
|
223
|
+
"markerInfoIcon": {
|
|
224
|
+
"position": 3,
|
|
225
|
+
"showArea": true,
|
|
226
|
+
"showPerimeter": true,
|
|
227
|
+
"useMetrics": true,
|
|
228
|
+
"usePerimeterMinValue": false,
|
|
229
|
+
"areaLabel": "Area",
|
|
230
|
+
"perimeterLabel": "Perimeter",
|
|
231
|
+
"values": {
|
|
232
|
+
"min": {
|
|
233
|
+
"metric": "50",
|
|
234
|
+
"imperial": "100"
|
|
235
|
+
},
|
|
236
|
+
"unknown": {
|
|
237
|
+
"metric": "-",
|
|
238
|
+
"imperial": "-"
|
|
239
|
+
}
|
|
240
|
+
},
|
|
241
|
+
"units": {
|
|
242
|
+
"unknownUnit": "",
|
|
243
|
+
"metric": {
|
|
244
|
+
"onlyMetrics": true,
|
|
245
|
+
"perimeter": {
|
|
246
|
+
"m": "m",
|
|
247
|
+
"km": "km"
|
|
248
|
+
},
|
|
249
|
+
"area": {
|
|
250
|
+
"m2": "m²",
|
|
251
|
+
"km2": "km²",
|
|
252
|
+
"daa": "daa",
|
|
253
|
+
"ha": "ha"
|
|
254
|
+
}
|
|
255
|
+
},
|
|
256
|
+
"imperial": {
|
|
257
|
+
"perimeter": {
|
|
258
|
+
"feet": "ft",
|
|
259
|
+
"yards": "yd",
|
|
260
|
+
"miles": "mi"
|
|
261
|
+
},
|
|
262
|
+
"area": {
|
|
263
|
+
"feet2": "ft²",
|
|
264
|
+
"yards2": "yd²",
|
|
265
|
+
"acres": "ac",
|
|
266
|
+
"miles2": "mi²"
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
},
|
|
270
|
+
"styleClasses": ["polygon-marker", "info"],
|
|
271
|
+
"zIndexOffset": 10000
|
|
272
|
+
},
|
|
273
|
+
"markerMenuIcon": {
|
|
274
|
+
"position": 7,
|
|
275
|
+
"styleClasses": ["polygon-marker", "menu"],
|
|
276
|
+
"zIndexOffset": 10000
|
|
277
|
+
},
|
|
278
|
+
"markerDeleteIcon": {
|
|
279
|
+
"position": 5,
|
|
280
|
+
"styleClasses": ["polygon-marker", "delete"],
|
|
281
|
+
"zIndexOffset": 10000
|
|
282
|
+
},
|
|
283
|
+
"visualOptimization": {
|
|
284
|
+
"sharpAngleThreshold": 30,
|
|
285
|
+
"thresholdBoundingBox": 0.05,
|
|
286
|
+
"thresholdDistance": 0.05,
|
|
287
|
+
"useDistance": true,
|
|
288
|
+
"useBoundingBox": false,
|
|
289
|
+
"useAngles": false
|
|
290
|
+
}
|
|
291
|
+
},
|
|
292
|
+
"polyLineOptions": {
|
|
293
|
+
"color": "#50622b",
|
|
294
|
+
"opacity": 1,
|
|
295
|
+
"smoothFactor": 0,
|
|
296
|
+
"noClip": true,
|
|
297
|
+
"clickable": false,
|
|
298
|
+
"weight": 2
|
|
299
|
+
},
|
|
300
|
+
"subtractLineOptions": {
|
|
301
|
+
"color": "#50622b",
|
|
302
|
+
"opacity": 1,
|
|
303
|
+
"smoothFactor": 0,
|
|
304
|
+
"noClip": true,
|
|
305
|
+
"clickable": false,
|
|
306
|
+
"weight": 2
|
|
307
|
+
},
|
|
308
|
+
"polygonOptions": {
|
|
309
|
+
"smoothFactor": 0.3,
|
|
310
|
+
"color": "#50622b",
|
|
311
|
+
"fillColor": "#b4cd8a",
|
|
312
|
+
"noClip": true
|
|
313
|
+
},
|
|
314
|
+
"holeOptions": {
|
|
315
|
+
"color": "#aa0000",
|
|
316
|
+
"fillColor": "#ffcccc",
|
|
317
|
+
"weight": 2,
|
|
318
|
+
"opacity": 1,
|
|
319
|
+
"fillOpacity": 0.5
|
|
320
|
+
},
|
|
321
|
+
"polygonCreation": {
|
|
322
|
+
"method": "concaveman",
|
|
323
|
+
"simplification": {
|
|
324
|
+
"mode": "simple",
|
|
325
|
+
"tolerance": 0.0001,
|
|
326
|
+
"highQuality": false
|
|
327
|
+
}
|
|
328
|
+
},
|
|
329
|
+
"simplification": {
|
|
330
|
+
"simplifyTolerance": {
|
|
331
|
+
"tolerance": 0.0001,
|
|
332
|
+
"highQuality": false,
|
|
333
|
+
"mutate": false
|
|
334
|
+
},
|
|
335
|
+
"dynamicMode": {
|
|
336
|
+
"fractionGuard": 0.9,
|
|
337
|
+
"multipiler": 2
|
|
338
|
+
}
|
|
339
|
+
},
|
|
340
|
+
"boundingBox": {
|
|
341
|
+
"addMidPointMarkers": true
|
|
342
|
+
},
|
|
343
|
+
"bezier": {
|
|
344
|
+
"resolution": 10000,
|
|
345
|
+
"sharpness": 0.75
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
### Configuration Options
|
|
351
|
+
|
|
352
|
+
| Key | Type | Default | Description |
|
|
353
|
+
| ------------------------------------------------------------------ | ------- | ------------------------------ | --------------------------------------------------------- |
|
|
354
|
+
| **touchSupport** | boolean | `true` | Enable touch support for mobile devices |
|
|
355
|
+
| **mergePolygons** | boolean | `true` | Auto-merge polygons during drawing when they intersect |
|
|
356
|
+
| **kinks** | boolean | `false` | Allow self-intersecting polygons |
|
|
357
|
+
| **modes** | object | | Feature toggles |
|
|
358
|
+
| draw | boolean | `true` | Enable draw mode button |
|
|
359
|
+
| subtract | boolean | `true` | Enable subtract mode button |
|
|
360
|
+
| deleteAll | boolean | `true` | Enable delete all button |
|
|
361
|
+
| p2p | boolean | `true` | Enable point-to-point drawing mode |
|
|
362
|
+
| attachElbow | boolean | `true` | Enable clicking on edges to add vertices |
|
|
363
|
+
| dragElbow | boolean | `true` | Enable dragging vertices |
|
|
364
|
+
| dragPolygons | boolean | `true` | Enable dragging entire polygons |
|
|
365
|
+
| edgeDeletion | boolean | `true` | Enable edge deletion with modifier keys |
|
|
366
|
+
| **dragPolygons** | object | | Polygon dragging configuration |
|
|
367
|
+
| realTimeUpdate | boolean | `false` | Update polygon position in real-time during drag |
|
|
368
|
+
| showDragHandle | boolean | `false` | Show visual drag handle on polygons |
|
|
369
|
+
| opacity | number | `0.7` | Polygon opacity during drag (0-1) |
|
|
370
|
+
| dragCursor | string | `"move"` | Cursor during active dragging |
|
|
371
|
+
| hoverCursor | string | `"grab"` | Cursor when hovering over draggable polygons |
|
|
372
|
+
| markerBehavior | string | `"hide"` | Marker behavior during drag: `"hide"`, `"show"`, `"fade"` |
|
|
373
|
+
| markerAnimationDuration | number | `200` | Duration of marker animations in milliseconds |
|
|
374
|
+
| autoMergeOnIntersect | boolean | `true` | Auto-merge when dragging polygons together |
|
|
375
|
+
| autoHoleOnContained | boolean | `false` | Create holes when dragging inside polygons |
|
|
376
|
+
| dragInteractionBehavior | string | `"auto"` | How drag interactions are handled |
|
|
377
|
+
| **modifierSubtract** | object | | Modifier key subtract configuration |
|
|
378
|
+
| enabled | boolean | `true` | Enable modifier key subtract mode |
|
|
379
|
+
| **keys** | object | | Platform-specific modifier keys |
|
|
380
|
+
| windows | string | `"ctrlKey"` | Windows modifier key |
|
|
381
|
+
| mac | string | `"metaKey"` | Mac modifier key |
|
|
382
|
+
| linux | string | `"ctrlKey"` | Linux modifier key |
|
|
383
|
+
| subtractColor | string | `"#D9460F"` | Color for subtract mode visualization |
|
|
384
|
+
| hideMarkersOnDrag | boolean | `true` | Hide markers during subtract drag |
|
|
385
|
+
| **edgeDeletion** | object | | Edge deletion configuration |
|
|
386
|
+
| enabled | boolean | `true` | Enable edge deletion functionality |
|
|
387
|
+
| modifierKey | string | `"auto"` | Modifier key: `"ctrl"`, `"cmd"`, `"auto"` |
|
|
388
|
+
| hoverColor | string | `"#D9460F"` | Color when hovering over deletable edges |
|
|
389
|
+
| confirmDeletion | boolean | `false` | Require confirmation before deleting |
|
|
390
|
+
| minVertices | number | `3` | Minimum vertices required after deletion |
|
|
391
|
+
| **markers** | object | | Marker configuration |
|
|
392
|
+
| deleteMarker | boolean | `true` | Show delete marker |
|
|
393
|
+
| infoMarker | boolean | `true` | Show info marker with area/perimeter |
|
|
394
|
+
| menuMarker | boolean | `true` | Show menu marker with operations |
|
|
395
|
+
| coordsTitle | boolean | `true` | Show coordinate tooltips on markers |
|
|
396
|
+
| zIndexOffset | number | `0` | Global z-index offset for markers |
|
|
397
|
+
| **markerIcon** | object | | Standard marker configuration |
|
|
398
|
+
| styleClasses | array | `["polygon-marker"]` | CSS classes for standard markers |
|
|
399
|
+
| zIndexOffset | number | `null` | Z-index offset override |
|
|
400
|
+
| **holeIcon** | object | | Hole marker configuration |
|
|
401
|
+
| styleClasses | array | `["polygon-marker", "hole"]` | CSS classes for hole markers |
|
|
402
|
+
| zIndexOffset | number | `null` | Z-index offset override |
|
|
403
|
+
| **markerInfoIcon** | object | | Info marker configuration |
|
|
404
|
+
| position | number | `3` | Marker position (see MarkerPosition enum) |
|
|
405
|
+
| showArea | boolean | `true` | Display area information |
|
|
406
|
+
| showPerimeter | boolean | `true` | Display perimeter information |
|
|
407
|
+
| useMetrics | boolean | `true` | Use metric units |
|
|
408
|
+
| usePerimeterMinValue | boolean | `false` | Use minimum value for small perimeters |
|
|
409
|
+
| areaLabel | string | `"Area"` | Label for area display |
|
|
410
|
+
| perimeterLabel | string | `"Perimeter"` | Label for perimeter display |
|
|
411
|
+
| **values** | object | | Default values configuration |
|
|
412
|
+
| **min** | object | | Minimum value settings |
|
|
413
|
+
| metric | string | `"50"` | Minimum metric value |
|
|
414
|
+
| imperial | string | `"100"` | Minimum imperial value |
|
|
415
|
+
| **unknown** | object | | Unknown value settings |
|
|
416
|
+
| metric | string | `"-"` | Unknown metric placeholder |
|
|
417
|
+
| imperial | string | `"-"` | Unknown imperial placeholder |
|
|
418
|
+
| **units** | object | | Unit configuration |
|
|
419
|
+
| unknownUnit | string | `""` | Unknown unit placeholder |
|
|
420
|
+
| **metric** | object | | Metric units |
|
|
421
|
+
| onlyMetrics | boolean | `true` | Use only m² and km² for area |
|
|
422
|
+
| **perimeter** | object | | Perimeter units |
|
|
423
|
+
| m | string | `"m"` | Meter unit |
|
|
424
|
+
| km | string | `"km"` | Kilometer unit |
|
|
425
|
+
| **area** | object | | Area units |
|
|
426
|
+
| m2 | string | `"m²"` | Square meter unit |
|
|
427
|
+
| km2 | string | `"km²"` | Square kilometer unit |
|
|
428
|
+
| daa | string | `"daa"` | Decare unit |
|
|
429
|
+
| ha | string | `"ha"` | Hectare unit |
|
|
430
|
+
| **imperial** | object | | Imperial units |
|
|
431
|
+
| **perimeter** | object | | Perimeter units |
|
|
432
|
+
| feet | string | `"ft"` | Feet unit |
|
|
433
|
+
| yards | string | `"yd"` | Yards unit |
|
|
434
|
+
| miles | string | `"mi"` | Miles unit |
|
|
435
|
+
| **area** | object | | Area units |
|
|
436
|
+
| feet2 | string | `"ft²"` | Square feet unit |
|
|
437
|
+
| yards2 | string | `"yd²"` | Square yards unit |
|
|
438
|
+
| acres | string | `"ac"` | Acres unit |
|
|
439
|
+
| miles2 | string | `"mi²"` | Square miles unit |
|
|
440
|
+
| styleClasses | array | `["polygon-marker", "info"]` | CSS classes for info marker |
|
|
441
|
+
| zIndexOffset | number | `10000` | Z-index offset for info marker |
|
|
442
|
+
| **markerMenuIcon** | object | | Menu marker configuration |
|
|
443
|
+
| position | number | `7` | Marker position (see MarkerPosition enum) |
|
|
444
|
+
| styleClasses | array | `["polygon-marker", "menu"]` | CSS classes for menu marker |
|
|
445
|
+
| zIndexOffset | number | `10000` | Z-index offset for menu marker |
|
|
446
|
+
| **markerDeleteIcon** | object | | Delete marker configuration |
|
|
447
|
+
| position | number | `5` | Marker position (see MarkerPosition enum) |
|
|
448
|
+
| styleClasses | array | `["polygon-marker", "delete"]` | CSS classes for delete marker |
|
|
449
|
+
| zIndexOffset | number | `10000` | Z-index offset for delete marker |
|
|
450
|
+
| **visualOptimization** | object | | Visual optimization settings |
|
|
451
|
+
| sharpAngleThreshold | number | `30` | Angle threshold for optimization |
|
|
452
|
+
| thresholdBoundingBox | number | `0.05` | Bounding box threshold |
|
|
453
|
+
| thresholdDistance | number | `0.05` | Distance threshold |
|
|
454
|
+
| useDistance | boolean | `true` | Use distance-based optimization |
|
|
455
|
+
| useBoundingBox | boolean | `false` | Use bounding box optimization |
|
|
456
|
+
| useAngles | boolean | `false` | Use angle-based optimization |
|
|
457
|
+
| **polyLineOptions** | object | | Polyline styling options |
|
|
458
|
+
| color | string | `"#50622b"` | Polyline color |
|
|
459
|
+
| opacity | number | `1` | Polyline opacity |
|
|
460
|
+
| smoothFactor | number | `0` | Polyline smoothing factor |
|
|
461
|
+
| noClip | boolean | `true` | Disable polyline clipping |
|
|
462
|
+
| clickable | boolean | `false` | Make polyline clickable |
|
|
463
|
+
| weight | number | `2` | Polyline weight in pixels |
|
|
464
|
+
| **subtractLineOptions** | object | | Subtract mode polyline styling |
|
|
465
|
+
| color | string | `"#50622b"` | Subtract polyline color |
|
|
466
|
+
| opacity | number | `1` | Subtract polyline opacity |
|
|
467
|
+
| smoothFactor | number | `0` | Subtract polyline smoothing |
|
|
468
|
+
| noClip | boolean | `true` | Disable subtract polyline clipping |
|
|
469
|
+
| clickable | boolean | `false` | Make subtract polyline clickable |
|
|
470
|
+
| weight | number | `2` | Subtract polyline weight |
|
|
471
|
+
| **polygonOptions** | object | | Polygon styling options |
|
|
472
|
+
| smoothFactor | number | `0.3` | Polygon smoothing factor |
|
|
473
|
+
| color | string | `"#50622b"` | Polygon border color |
|
|
474
|
+
| fillColor | string | `"#b4cd8a"` | Polygon fill color |
|
|
475
|
+
| noClip | boolean | `true` | Disable polygon clipping |
|
|
476
|
+
| **holeOptions** | object | | Hole styling options |
|
|
477
|
+
| color | string | `"#aa0000"` | Hole border color |
|
|
478
|
+
| fillColor | string | `"#ffcccc"` | Hole fill color |
|
|
479
|
+
| weight | number | `2` | Hole border weight |
|
|
480
|
+
| opacity | number | `1` | Hole border opacity |
|
|
481
|
+
| fillOpacity | number | `0.5` | Hole fill opacity |
|
|
482
|
+
| **polygonCreation** | object | | Polygon creation settings |
|
|
483
|
+
| method | string | `"concaveman"` | Creation method |
|
|
484
|
+
| **simplification** | object | | Creation simplification |
|
|
485
|
+
| mode | string | `"simple"` | Simplification mode |
|
|
486
|
+
| tolerance | number | `0.0001` | Simplification tolerance |
|
|
487
|
+
| highQuality | boolean | `false` | High quality simplification |
|
|
488
|
+
| **simplification** | object | | General simplification settings |
|
|
489
|
+
| **simplifyTolerance** | object | | Tolerance settings |
|
|
490
|
+
| tolerance | number | `0.0001` | Simplification tolerance |
|
|
491
|
+
| highQuality | boolean | `false` | High quality mode |
|
|
492
|
+
| mutate | boolean | `false` | Allow input mutation |
|
|
493
|
+
| **dynamicMode** | object | | Dynamic simplification |
|
|
494
|
+
| fractionGuard | number | `0.9` | Fraction guard value |
|
|
495
|
+
| multipiler | number | `2` | Tolerance multiplier |
|
|
496
|
+
| **boundingBox** | object | | Bounding box settings |
|
|
497
|
+
| addMidPointMarkers | boolean | `true` | Add midpoint markers to bounding box |
|
|
498
|
+
| **bezier** | object | | Bezier curve settings |
|
|
499
|
+
| resolution | number | `10000` | Bezier curve resolution |
|
|
500
|
+
| sharpness | number | `0.75` | Bezier curve sharpness |
|
|
501
|
+
|
|
502
|
+
### External Configuration
|
|
503
|
+
|
|
504
|
+
Load configuration from an external JSON file:
|
|
505
|
+
|
|
506
|
+
```javascript
|
|
507
|
+
const polyDrawControl = L.control.polydraw({
|
|
508
|
+
configPath: 'path/to/your/polydraw.config.json',
|
|
509
|
+
});
|
|
510
|
+
```
|
|
511
|
+
|
|
512
|
+
You can also combine external configuration with inline configuration. Inline configuration takes precedence:
|
|
513
|
+
|
|
514
|
+
```javascript
|
|
515
|
+
const polyDrawControl = L.control.polydraw({
|
|
516
|
+
configPath: 'config/polydraw.json',
|
|
517
|
+
config: {
|
|
518
|
+
// These settings will override the external config
|
|
519
|
+
polygonOptions: {
|
|
520
|
+
color: '#ff0000',
|
|
521
|
+
},
|
|
522
|
+
},
|
|
523
|
+
});
|
|
524
|
+
```
|
|
525
|
+
|
|
526
|
+
**Configuration Priority (highest to lowest):**
|
|
527
|
+
|
|
528
|
+
1. Inline `config` parameter
|
|
529
|
+
2. External configuration file
|
|
530
|
+
3. Default configuration
|
|
531
|
+
|
|
532
|
+
If the external configuration file fails to load, the plugin will fall back to using the default configuration plus any inline configuration provided.
|
|
533
|
+
|
|
534
|
+
## Features
|
|
535
|
+
|
|
536
|
+
### Draw Mode
|
|
537
|
+
|
|
538
|
+
[](https://raw.githubusercontent.com/AndreasOlausson/leaflet-polydraw/main/Leaflet.Polydraw/docs/images/draw-mode.gif)
|
|
539
|
+
|
|
540
|
+
Create polygons by drawing freehand shapes on the map. Perfect for:
|
|
541
|
+
|
|
542
|
+
- Quick area sketching
|
|
543
|
+
- Rough boundary mapping
|
|
544
|
+
- Freehand polygon creation
|
|
545
|
+
- Natural drawing workflow
|
|
546
|
+
|
|
547
|
+
Simply click the draw button and drag your mouse/finger to create polygon shapes. The plugin automatically converts your drawn path into a clean polygon using advanced algorithms.
|
|
548
|
+
|
|
549
|
+
**Note**: The number of vertices in the final polygon is controlled by the `polygonCreation.simplification` settings in the configuration.
|
|
550
|
+
|
|
551
|
+
### Subtract Mode
|
|
552
|
+
|
|
553
|
+
[](https://raw.githubusercontent.com/AndreasOlausson/leaflet-polydraw/main/Leaflet.Polydraw/docs/images/subtract-mode.gif)
|
|
554
|
+
|
|
555
|
+
Create holes and complex shapes by subtracting areas from existing polygons. Ideal for:
|
|
556
|
+
|
|
557
|
+
- Creating holes in polygons
|
|
558
|
+
- Removing unwanted areas
|
|
559
|
+
- Complex shape editing
|
|
560
|
+
- Precision area exclusion
|
|
561
|
+
|
|
562
|
+
Click the subtract button and draw over existing polygons to remove those areas, creating holes or splitting polygons into multiple parts.
|
|
563
|
+
|
|
564
|
+
### Point-to-Point Drawing
|
|
565
|
+
|
|
566
|
+
[](https://raw.githubusercontent.com/AndreasOlausson/leaflet-polydraw/main/Leaflet.Polydraw/docs/images/p2p.gif)
|
|
567
|
+
|
|
568
|
+
Create precise polygons by clicking to place each vertex. Perfect for:
|
|
569
|
+
|
|
570
|
+
- Accurate boundary mapping
|
|
571
|
+
- Property delineation
|
|
572
|
+
- Custom shape creation
|
|
573
|
+
|
|
574
|
+
**How it works:**
|
|
575
|
+
|
|
576
|
+
1. Click to place the first vertex.
|
|
577
|
+
2. Continue clicking to add more vertices.
|
|
578
|
+
3. To complete the polygon (requires minimum 3 points):
|
|
579
|
+
- Click on the first vertex again.
|
|
580
|
+
- **or** Double-click anywhere on the map.
|
|
581
|
+
4. Press `ESC` to cancel the current drawing.
|
|
582
|
+
|
|
583
|
+
### Smart Polygon Merging
|
|
584
|
+
|
|
585
|
+
[](https://raw.githubusercontent.com/AndreasOlausson/leaflet-polydraw/main/Leaflet.Polydraw/docs/images/merge.gif)
|
|
586
|
+
|
|
587
|
+
The plugin features **two independent merge systems**:
|
|
588
|
+
|
|
589
|
+
#### 1. Drawing Merge (`mergePolygons`)
|
|
590
|
+
|
|
591
|
+
- **When**: During polygon creation
|
|
592
|
+
- **Purpose**: Automatically merge new polygons with existing intersecting ones
|
|
593
|
+
- **Use case**: Streamlined drawing workflow
|
|
594
|
+
|
|
595
|
+
#### 2. Drag Merge (`autoMergeOnIntersect`)
|
|
596
|
+
|
|
597
|
+
- **When**: During polygon dragging
|
|
598
|
+
- **Purpose**: Merge polygons when dragged together
|
|
599
|
+
- **Use case**: Interactive editing and combining
|
|
600
|
+
|
|
601
|
+
### Drag & Drop Functionality
|
|
602
|
+
|
|
603
|
+
[](https://raw.githubusercontent.com/AndreasOlausson/leaflet-polydraw/main/Leaflet.Polydraw/docs/images/drag-drop.gif)
|
|
604
|
+
|
|
605
|
+
**Drag-to-Merge**: Drag polygons together to automatically merge them
|
|
606
|
+
|
|
607
|
+
**Drag-to-Hole**: Drag a polygon completely inside another to create a hole (requires a modifier key defined in `config.dragPolygons.modifierSubtract.keys`)
|
|
608
|
+
|
|
609
|
+
**Repositioning**: Drag to empty areas to simply reposition polygons
|
|
610
|
+
|
|
611
|
+
### Drag Elbows (Vertex Editing)
|
|
612
|
+
|
|
613
|
+
[](https://raw.githubusercontent.com/AndreasOlausson/leaflet-polydraw/main/Leaflet.Polydraw/docs/images/drag-elbows.gif)
|
|
614
|
+
|
|
615
|
+
Fine-tune polygon shapes by dragging individual vertices. Perfect for:
|
|
616
|
+
|
|
617
|
+
- Precision boundary adjustments
|
|
618
|
+
- Shape refinement after initial drawing
|
|
619
|
+
- Correcting polygon edges
|
|
620
|
+
- Detailed polygon editing
|
|
621
|
+
|
|
622
|
+
Click and drag any vertex (elbow) to reshape your polygons. To add a new vertex, click directly on the line between two existing points. To remove a vertex, hold the configured modifier key (defined in `config.dragPolygons.modifierSubtract.keys`) and click the vertex you want to delete. This provides full control over polygon geometry and shape refinement.
|
|
623
|
+
|
|
624
|
+
### Advanced Editing Tools
|
|
625
|
+
|
|
626
|
+
[](https://raw.githubusercontent.com/AndreasOlausson/leaflet-polydraw/main/Leaflet.Polydraw/docs/images/editing-tools.gif)
|
|
627
|
+
|
|
628
|
+
Access operations through the menu marker:
|
|
629
|
+
|
|
630
|
+
- **Simplify**: Reduce polygon complexity using Douglas-Peucker algorithm
|
|
631
|
+
- **Double Elbows**: Add intermediate vertices for higher resolution
|
|
632
|
+
- **Bounding Box**: Convert to rectangular bounds
|
|
633
|
+
- **Bezier Curves**: Apply smooth curve interpolation (alpha)
|
|
634
|
+
|
|
635
|
+
### Smart Marker System
|
|
636
|
+
|
|
637
|
+
[](https://raw.githubusercontent.com/AndreasOlausson/leaflet-polydraw/main/Leaflet.Polydraw/docs/images/smart-markers.png)
|
|
638
|
+
|
|
639
|
+
Intelligent marker positioning prevents overlapping on small polygons:
|
|
640
|
+
|
|
641
|
+
- **Automatic separation**: Detects potential overlaps and redistributes markers
|
|
642
|
+
- **Priority-based**: Resolves conflicts using info → delete → menu priority
|
|
643
|
+
- **Smooth animations**: Markers fade during drag operations
|
|
644
|
+
|
|
645
|
+
## API Reference
|
|
646
|
+
|
|
647
|
+
For most use cases, simply add the plugin and use the built-in buttons. However, these methods are available for programmatic control:
|
|
648
|
+
|
|
649
|
+
### Essential Methods
|
|
650
|
+
|
|
651
|
+
#### `addPredefinedPolygon(geographicBorders: L.LatLng[][][])`
|
|
652
|
+
|
|
653
|
+
Add polygons programmatically (useful for loading saved data).
|
|
654
|
+
|
|
655
|
+
```javascript
|
|
656
|
+
const polygon = [
|
|
657
|
+
[
|
|
658
|
+
[
|
|
659
|
+
{ lat: 59.903, lng: 10.724 },
|
|
660
|
+
{ lat: 59.908, lng: 10.728 },
|
|
661
|
+
{ lat: 59.91, lng: 10.72 },
|
|
662
|
+
{ lat: 59.903, lng: 10.724 },
|
|
663
|
+
],
|
|
664
|
+
],
|
|
665
|
+
];
|
|
666
|
+
polydraw.addPredefinedPolygon(polygon);
|
|
667
|
+
```
|
|
668
|
+
|
|
669
|
+
#### `getAllPolygons()`
|
|
670
|
+
|
|
671
|
+
Get all polygons for data export.
|
|
672
|
+
|
|
673
|
+
```javascript
|
|
674
|
+
const polygons = polydraw.getAllPolygons();
|
|
675
|
+
// Use for saving, exporting, or processing polygon data
|
|
676
|
+
```
|
|
677
|
+
|
|
678
|
+
### Advanced Methods (Optional)
|
|
679
|
+
|
|
680
|
+
#### `setDrawMode(mode: DrawMode)` & `getDrawMode()`
|
|
681
|
+
|
|
682
|
+
Programmatically control drawing modes (the buttons do this automatically).
|
|
683
|
+
|
|
684
|
+
```javascript
|
|
685
|
+
import { DrawMode } from 'leaflet-polydraw';
|
|
686
|
+
polydraw.setDrawMode(DrawMode.Add); // Same as clicking the draw button
|
|
687
|
+
```
|
|
688
|
+
|
|
689
|
+
#### `configurate(config: any)`
|
|
690
|
+
|
|
691
|
+
Update configuration after initialization.
|
|
692
|
+
|
|
693
|
+
```javascript
|
|
694
|
+
polydraw.configurate({
|
|
695
|
+
polygonOptions: { color: '#ff0000' },
|
|
696
|
+
});
|
|
697
|
+
```
|
|
698
|
+
|
|
699
|
+
## Markers
|
|
700
|
+
|
|
701
|
+
[](https://raw.githubusercontent.com/AndreasOlausson/leaflet-polydraw/main/Leaflet.Polydraw/docs/images/marker-positions.png)
|
|
702
|
+
|
|
703
|
+
### Delete Marker (Default: North)
|
|
704
|
+
|
|
705
|
+
- **Purpose**: Delete the entire polygon
|
|
706
|
+
- **Icon**: Trash/delete icon
|
|
707
|
+
- **Behavior**: Fades during drag operations
|
|
708
|
+
|
|
709
|
+
### Info Marker (Default: East)
|
|
710
|
+
|
|
711
|
+
- **Purpose**: Display polygon metrics
|
|
712
|
+
- **Features**: Area, perimeter, metric/imperial units
|
|
713
|
+
- **Popup**: Shows detailed measurements
|
|
714
|
+
|
|
715
|
+
[](https://raw.githubusercontent.com/AndreasOlausson/leaflet-polydraw/main/Leaflet.Polydraw/docs/images/info-marker-popup.png)
|
|
716
|
+
|
|
717
|
+
### Menu Marker (Default: West)
|
|
718
|
+
|
|
719
|
+
- **Purpose**: Access advanced polygon editing operations
|
|
720
|
+
- **Popup**: Interactive operation menu with the following tools:
|
|
721
|
+
- **Simplify**: Reduce polygon complexity by removing unnecessary vertices using Douglas-Peucker algorithm
|
|
722
|
+
- **Double Elbows**: Add intermediate vertices between existing points for higher resolution editing
|
|
723
|
+
- **Bounding Box**: Convert polygon to its rectangular bounding box
|
|
724
|
+
- **Bezier**: Apply smooth curve interpolation to polygon edges _(alpha feature)_
|
|
725
|
+
|
|
726
|
+
[](https://raw.githubusercontent.com/AndreasOlausson/leaflet-polydraw/main/Leaflet.Polydraw/docs/images/menu-marker-popup.png)
|
|
727
|
+
|
|
728
|
+
### Marker Positioning
|
|
729
|
+
|
|
730
|
+
Customize marker positions using the `MarkerPosition` enum:
|
|
731
|
+
|
|
732
|
+
```javascript
|
|
733
|
+
const polyDrawControl = L.control.polydraw({
|
|
734
|
+
config: {
|
|
735
|
+
markers: {
|
|
736
|
+
markerDeleteIcon: {
|
|
737
|
+
position: MarkerPosition.North,
|
|
738
|
+
styleClasses: ['custom-delete-marker'],
|
|
739
|
+
},
|
|
740
|
+
markerInfoIcon: {
|
|
741
|
+
position: MarkerPosition.East,
|
|
742
|
+
useMetrics: true,
|
|
743
|
+
areaLabel: 'Area',
|
|
744
|
+
perimeterLabel: 'Perimeter',
|
|
745
|
+
},
|
|
746
|
+
markerMenuIcon: {
|
|
747
|
+
position: MarkerPosition.West,
|
|
748
|
+
styleClasses: ['custom-menu-marker'],
|
|
749
|
+
},
|
|
750
|
+
},
|
|
751
|
+
},
|
|
752
|
+
});
|
|
753
|
+
```
|
|
754
|
+
|
|
755
|
+
This configuration gives this result.
|
|
756
|
+
|
|
757
|
+

|
|
758
|
+
|
|
759
|
+
```javascript
|
|
760
|
+
MarkerPosition {
|
|
761
|
+
SouthWest = 0,
|
|
762
|
+
South = 1,
|
|
763
|
+
SouthEast = 2,
|
|
764
|
+
East = 3,
|
|
765
|
+
NorthEast = 4,
|
|
766
|
+
North = 5,
|
|
767
|
+
NorthWest = 6,
|
|
768
|
+
West = 7
|
|
769
|
+
}
|
|
770
|
+
```
|
|
771
|
+
|
|
772
|
+
## Events
|
|
773
|
+
|
|
774
|
+
Polydraw emits various events that allow you to respond to user interactions and polygon changes. These events are useful for implementing features like auto-save, validation, analytics, or custom UI updates.
|
|
775
|
+
|
|
776
|
+
### Draw Mode Events
|
|
777
|
+
|
|
778
|
+
Listen for drawing mode changes to update your UI or trigger specific behaviors:
|
|
779
|
+
|
|
780
|
+
```javascript
|
|
781
|
+
polydraw.onDrawModeChanged((mode) => {
|
|
782
|
+
console.log('Draw mode changed to:', mode);
|
|
783
|
+
|
|
784
|
+
// Update UI based on current mode
|
|
785
|
+
switch (mode) {
|
|
786
|
+
case DrawMode.Add:
|
|
787
|
+
updateStatusBar('Drawing mode: Add polygons');
|
|
788
|
+
break;
|
|
789
|
+
case DrawMode.Subtract:
|
|
790
|
+
updateStatusBar('Drawing mode: Create holes');
|
|
791
|
+
break;
|
|
792
|
+
case DrawMode.Off:
|
|
793
|
+
updateStatusBar('Drag mode: Move polygons');
|
|
794
|
+
break;
|
|
795
|
+
}
|
|
796
|
+
});
|
|
797
|
+
```
|
|
798
|
+
|
|
799
|
+
### Polygon Lifecycle Events
|
|
800
|
+
|
|
801
|
+
Track polygon creation, modification, and deletion:
|
|
802
|
+
|
|
803
|
+
```javascript
|
|
804
|
+
// Polygon created
|
|
805
|
+
map.on('polygon:created', (e) => {
|
|
806
|
+
console.log('New polygon created:', e.polygon);
|
|
807
|
+
// Auto-save, validate, or log the new polygon
|
|
808
|
+
savePolygonToDatabase(e.polygon);
|
|
809
|
+
});
|
|
810
|
+
|
|
811
|
+
// Polygon modified (vertices moved, simplified, etc.)
|
|
812
|
+
map.on('polygon:modified', (e) => {
|
|
813
|
+
console.log('Polygon modified:', e.polygon);
|
|
814
|
+
// Mark as unsaved, trigger validation
|
|
815
|
+
markAsUnsaved(e.polygon);
|
|
816
|
+
});
|
|
817
|
+
|
|
818
|
+
// Polygon deleted
|
|
819
|
+
map.on('polygon:deleted', (e) => {
|
|
820
|
+
console.log('Polygon deleted:', e.polygon);
|
|
821
|
+
// Remove from database, update counters
|
|
822
|
+
removeFromDatabase(e.polygonId);
|
|
823
|
+
});
|
|
824
|
+
```
|
|
825
|
+
|
|
826
|
+
### Drag & Drop Events
|
|
827
|
+
|
|
828
|
+
Monitor polygon dragging for real-time updates or validation:
|
|
829
|
+
|
|
830
|
+
```javascript
|
|
831
|
+
// Drag start - useful for showing drag indicators
|
|
832
|
+
map.on('polygon:dragstart', (e) => {
|
|
833
|
+
console.log('Drag started:', e.polygon);
|
|
834
|
+
showDragIndicator(true);
|
|
835
|
+
logUserAction('drag_start', e.polygon.id);
|
|
836
|
+
});
|
|
837
|
+
|
|
838
|
+
// Drag end - perfect for auto-save or validation
|
|
839
|
+
map.on('polygon:dragend', (e) => {
|
|
840
|
+
console.log('Drag ended:', e.polygon);
|
|
841
|
+
console.log('Moved from:', e.oldPosition, 'to:', e.newPosition);
|
|
842
|
+
|
|
843
|
+
showDragIndicator(false);
|
|
844
|
+
autoSavePolygon(e.polygon);
|
|
845
|
+
validatePolygonPosition(e.polygon);
|
|
846
|
+
});
|
|
847
|
+
|
|
848
|
+
// Real-time drag updates (if realTimeUpdate is enabled)
|
|
849
|
+
map.on('polygon:drag', (e) => {
|
|
850
|
+
console.log('Dragging:', e.polygon);
|
|
851
|
+
updateCoordinateDisplay(e.polygon.getLatLngs());
|
|
852
|
+
});
|
|
853
|
+
```
|
|
854
|
+
|
|
855
|
+
### Merge & Hole Events
|
|
856
|
+
|
|
857
|
+
Track automatic merging and hole creation:
|
|
858
|
+
|
|
859
|
+
```javascript
|
|
860
|
+
// Polygons merged automatically
|
|
861
|
+
map.on('polygons:merged', (e) => {
|
|
862
|
+
console.log('Polygons merged:', e.originalPolygons, '→', e.resultPolygon);
|
|
863
|
+
updatePolygonCount(-e.originalPolygons.length + 1);
|
|
864
|
+
});
|
|
865
|
+
|
|
866
|
+
// Hole created by dragging polygon inside another
|
|
867
|
+
map.on('polygon:hole-created', (e) => {
|
|
868
|
+
console.log('Hole created in:', e.parentPolygon, 'by:', e.holePolygon);
|
|
869
|
+
notifyUser('Hole created in polygon');
|
|
870
|
+
});
|
|
871
|
+
```
|
|
872
|
+
|
|
873
|
+
### Practical Use Cases
|
|
874
|
+
|
|
875
|
+
**Auto-save functionality:**
|
|
876
|
+
|
|
877
|
+
```javascript
|
|
878
|
+
map.on('polygon:created polygon:modified polygon:dragend', (e) => {
|
|
879
|
+
debounce(() => saveToLocalStorage(polydraw.getAllPolygons()), 1000);
|
|
880
|
+
});
|
|
881
|
+
```
|
|
882
|
+
|
|
883
|
+
**Validation and feedback:**
|
|
884
|
+
|
|
885
|
+
```javascript
|
|
886
|
+
map.on('polygon:created', (e) => {
|
|
887
|
+
const area = calculateArea(e.polygon);
|
|
888
|
+
if (area < MIN_AREA) {
|
|
889
|
+
showWarning('Polygon too small');
|
|
890
|
+
e.polygon.setStyle({ color: 'red' });
|
|
891
|
+
}
|
|
892
|
+
});
|
|
893
|
+
```
|
|
894
|
+
|
|
895
|
+
**Analytics tracking:**
|
|
896
|
+
|
|
897
|
+
```javascript
|
|
898
|
+
polydraw.onDrawModeChanged((mode) => {
|
|
899
|
+
analytics.track('draw_mode_changed', { mode: mode });
|
|
900
|
+
});
|
|
901
|
+
|
|
902
|
+
map.on('polygon:created', (e) => {
|
|
903
|
+
analytics.track('polygon_created', {
|
|
904
|
+
vertices: e.polygon.getLatLngs()[0].length,
|
|
905
|
+
area: calculateArea(e.polygon),
|
|
906
|
+
});
|
|
907
|
+
});
|
|
908
|
+
```
|
|
909
|
+
|
|
910
|
+
## Browser Support
|
|
911
|
+
|
|
912
|
+
- **Modern Browsers**: Chrome 60+, Firefox 55+, Safari 12+, Edge 79+
|
|
913
|
+
- **Mobile**: iOS Safari 12+, Chrome Mobile 60+
|
|
914
|
+
- **Requirements**: ES6+ support, Leaflet 1.9+, Touch events, CSS transitions
|
|
915
|
+
|
|
916
|
+
## Demo
|
|
917
|
+
|
|
918
|
+
A local demo is included in the `demo/` directory for testing and development purposes.
|
|
919
|
+
|
|
920
|
+
### Running the Demo
|
|
921
|
+
|
|
922
|
+
To run the local demo:
|
|
923
|
+
|
|
924
|
+
1. **Build the main library and types**:
|
|
925
|
+
|
|
926
|
+
```bash
|
|
927
|
+
cd Leaflet.Polydraw
|
|
928
|
+
npm run build
|
|
929
|
+
npm run build:types
|
|
930
|
+
```
|
|
931
|
+
|
|
932
|
+
2. **Run the demo**:
|
|
933
|
+
```bash
|
|
934
|
+
cd demo
|
|
935
|
+
npm install
|
|
936
|
+
npm run dev
|
|
937
|
+
```
|
|
938
|
+
|
|
939
|
+
The demo will be available at `http://localhost:5173/` and includes examples of all major features.
|
|
940
|
+
|
|
941
|
+
## Contributing
|
|
942
|
+
|
|
943
|
+
Contributions are welcome! Please feel free to submit a Pull Request.
|
|
944
|
+
|
|
945
|
+
### Development Setup
|
|
946
|
+
|
|
947
|
+
```bash
|
|
948
|
+
# Clone the repository
|
|
949
|
+
git clone https://github.com/AndreasOlausson/leaflet-polydraw.git
|
|
950
|
+
cd leaflet-polydraw
|
|
951
|
+
|
|
952
|
+
# Install dependencies
|
|
953
|
+
npm install
|
|
954
|
+
|
|
955
|
+
# Run tests
|
|
956
|
+
npm test
|
|
957
|
+
|
|
958
|
+
# Build the project
|
|
959
|
+
npm run build
|
|
960
|
+
npm run build:types
|
|
961
|
+
|
|
962
|
+
# For development with the demo project
|
|
963
|
+
cd demo
|
|
964
|
+
npm install
|
|
965
|
+
npm run dev # Automatically builds plugin, generates typings, and installs them
|
|
966
|
+
```
|
|
967
|
+
|
|
968
|
+
**Note**: The demo's `npm run dev` command automatically rebuilds the main plugin and type definitions, then installs them locally for immediate testing of your changes.
|
|
969
|
+
|
|
970
|
+
### Guidelines
|
|
971
|
+
|
|
972
|
+
- Follow the existing coding style
|
|
973
|
+
- Add tests for new features
|
|
974
|
+
- Update documentation when relevant
|
|
975
|
+
- Ensure all tests pass before submitting
|
|
976
|
+
|
|
977
|
+
## License
|
|
978
|
+
|
|
979
|
+
This project is licensed under the [MIT License](./LICENSE).
|
|
980
|
+
|
|
981
|
+
## Acknowledgments
|
|
982
|
+
|
|
983
|
+
PolyDraw was initially inspired by:
|
|
984
|
+
|
|
985
|
+
- [Leaflet.FreeDraw](https://github.com/Wildhoney/Leaflet.FreeDraw) by Adam Timberlake "Wildhoney"
|
|
986
|
+
- [leaflet-freehandshapes](https://github.com/bozdoz/leaflet-freehandshapes) by Benjamin DeLong "bozdoz"
|
|
987
|
+
|
|
988
|
+
Big thank you and kudos to these amazing developers!
|
|
989
|
+
|
|
990
|
+
## Changelog
|
|
991
|
+
|
|
992
|
+
### v0.8.0 (Initial release)
|
|
993
|
+
|
|
994
|
+
- **Polygon Dragging**: Complete drag-and-drop functionality
|
|
995
|
+
- **Smart Merging**: Dual merge systems for drawing and dragging
|
|
996
|
+
- **Marker Separation**: Intelligent positioning prevents overlaps
|
|
997
|
+
- **Enhanced Events**: Comprehensive event system
|
|
998
|
+
- **Production Ready**: 167+ passing tests, full TypeScript support
|
|
999
|
+
- **Performance Optimized**: Efficient geometric operations
|
|
1000
|
+
|
|
1001
|
+
---
|
|
1002
|
+
|
|
1003
|
+
**Created and maintained by [Andreas Olausson](https://github.com/AndreasOlausson)**
|
|
1004
|
+
|
|
1005
|
+
[](https://github.com/AndreasOlausson/leaflet-polydraw)
|
|
1006
|
+
[](https://github.com/AndreasOlausson/leaflet-polydraw/fork)
|