diff --git a/README.md b/README.md
index 71b7a95e..7a591740 100644
--- a/README.md
+++ b/README.md
@@ -9,7 +9,7 @@
Leaflet Plugin For Creating And Editing Geometry Layers
Draw, Edit, Drag, Cut, Rotate, Split⭐, Scale⭐, Measure⭐, Snap and Pin⭐ Layers
- Supports Markers, CircleMarkers, Polylines, Polygons, Circles, Rectangles, ImageOverlays, LayerGroups, GeoJSON, MultiLineStrings and MultiPolygons
+ Supports Markers, CircleMarkers, Polylines, Curves, Polygons, Circles, Rectangles, ImageOverlays, LayerGroups, GeoJSON, MultiLineStrings and MultiPolygons
@@ -199,6 +199,7 @@ See the available options in the table below.
| drawPolyline | `true` | Adds button to draw Line. |
| drawRectangle | `true` | Adds button to draw Rectangle. |
| drawPolygon | `true` | Adds button to draw Polygon. |
+| drawCurve | `true` | Adds button to draw Curve. |
| drawCircle | `true` | Adds button to draw Circle. |
| editMode | `true` | Adds button to toggle Edit Mode for all layers. |
| dragMode | `true` | Adds button to toggle Drag Mode for all layers. |
@@ -229,6 +230,11 @@ The options will persist, even when the mode is enabled/disabled via the toolbar
All available options for drawing and editing are specified in the sections below.
+#### Drawing curves
+The drawing of curves is enabled by default, if [Leaflet.curve](https://github.com/elfalem/Leaflet.curve) is imported. Otherwise the tool will not be available.
+At the moment, the feature to detect self intersection is not available for curves. Similarly, the cutting tool won't work on them.
+
+
### Draw Mode
Use Draw Mode on a map like this:
@@ -244,7 +250,7 @@ map.pm.enableDraw('Polygon', {
map.pm.disableDraw();
```
-Currently available shapes are `Marker`, `CircleMarker`, `Circle`, `Line`, `Rectangle`, `Polygon` and `Cut`.
+Currently available shapes are `Marker`, `CircleMarker`, `Circle`, `Line`, `Curve`, `Rectangle`, `Polygon` and `Cut`.
The following methods are available on `map.pm`:
@@ -759,7 +765,7 @@ The following options are additionally to the [Draw](#draw-mode) and [Edit Mode]
| Option | Default | Description |
| :------------ | :------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| snappingOrder | `Array` | Prioritize the order of snapping. Default: `['Marker','CircleMarker','Circle','Line','Polygon','Rectangle']`. |
+| snappingOrder | `Array` | Prioritize the order of snapping. Default: `['Marker','CircleMarker','Circle','Line','Polygon','Rectangle','Curve']`. |
| layerGroup | `map` | add the created layers to a layergroup instead to the map. |
| panes | `Object` | Defines in which [panes](https://leafletjs.com/reference-1.7.1.html#map-pane) the layers and helper vertices are created. Default: `{ vertexPane: 'markerPane', layerPane: 'overlayPane', markerPane: 'markerPane' }`. |
diff --git a/cypress/integration/curve.spec.js b/cypress/integration/curve.spec.js
new file mode 100644
index 00000000..7cbd251a
--- /dev/null
+++ b/cypress/integration/curve.spec.js
@@ -0,0 +1,213 @@
+describe('Draw & Edit Curve', () => {
+ // map and leaflet object
+
+ const mapSelector = '#map';
+
+ it('doesnt finish single point curves', () => {
+ cy.toolbarButton('curve').click();
+
+ cy.get(mapSelector).click(90, 250).click(200, 250);
+
+ cy.toolbarButton('edit').click();
+
+ cy.hasVertexMarkers(0);
+ });
+
+ it('removes last vertex', () => {
+ cy.toolbarButton('curve').click();
+
+ cy.get(mapSelector)
+ .click(190, 250)
+ .trigger('mousedown', 500, 250)
+ .trigger('mousemove', 500, 300)
+ .trigger('mousemove', 400, 350)
+ .trigger('mouseup')
+
+ cy.hasVertexMarkers(3); // 2 + mouse
+
+ cy.get('.button-container.active .action-removeLastVertex').click();
+
+ cy.hasVertexMarkers(2); // first + mouse
+
+ cy.get('.button-container.active .action-removeLastVertex').click();
+
+ cy.hasVertexMarkers(0); // remove all
+ });
+
+ it('respects custom style', () => {
+ cy.window().then(({ map }) => {
+ map.on('pm:create', (e) => {
+ e.layer.pm.enable({
+ allowSelfIntersection: false,
+ snappable: false,
+ snapDistance: 20,
+ });
+
+ e.layer.setStyle({ color: 'black' });
+ });
+
+ map.pm.enableDraw('Curve', {
+ snappable: false,
+ snapDistance: 20,
+ allowSelfIntersection: true,
+ finishOn: 'dblclick',
+ templineStyle: {
+ color: 'orange',
+ dashArray: [10, 10],
+ weight: 5,
+ },
+ hintlineStyle: {
+ color: 'orange',
+ dashArray: [10, 10],
+ weight: 1,
+ },
+ pathOptions: {
+ fill: true,
+ color: 'orange',
+ fillColor: 'yellow',
+ dashArray: [10, 10],
+ weight: 5,
+ fillOpacity: 1,
+ opacity: 1,
+ },
+ });
+ });
+
+ cy.get(mapSelector)
+ .click(120, 150)
+ .click(120, 100)
+ .click(300, 100)
+ .click(300, 200)
+ .click(120, 150);
+
+ cy.toolbarButton('curve').click();
+
+ cy.get(mapSelector)
+ .click(320, 150)
+ .click(320, 100)
+ .click(400, 100)
+ .click(400, 200)
+ .click(320, 150);
+
+ cy.toolbarButton('edit').click();
+
+ cy.window().then(({ map, L }) => {
+ map.eachLayer((l) => {
+ if (l instanceof L.Curve) expect(l.options.color).to.equal('black');
+ });
+ });
+ });
+
+ it('draws and edits a curve', () => {
+ cy.hasLayers(1);
+
+ // activate curve drawing
+ cy.toolbarButton('curve')
+ .click()
+ .closest('.button-container')
+ .should('have.class', 'active');
+
+ // draw a curve
+ cy.get(mapSelector)
+ .click(190, 250)
+ .trigger('mousedown', 500, 250)
+ .trigger('mousemove', 500, 300)
+ .trigger('mousemove', 400, 350)
+ .trigger('mouseup')
+ .click(190, 250)
+
+ // button should be disabled after successful draw
+ cy.toolbarButton('curve')
+ .closest('.button-container')
+ .should('have.not.class', 'active');
+
+ cy.hasLayers(3);
+
+ // enable global edit mode
+ cy.toolbarButton('edit').click();
+
+ cy.hasVertexMarkers(3);
+
+ // click the second marker (cubic edit)
+ cy.get('.marker-icon').eq(1).click();
+
+ // now there should be 2 editing handles
+ cy.hasHandleMarkers(2);
+
+ // rightclick on a vertex-marker to delete it
+ cy.get('.marker-icon:not(.marker-edit-handle)')
+ .eq(1)
+ .trigger('contextmenu');
+
+ cy.hasVertexMarkers(2);
+ // handle markers should disappear
+ cy.hasHandleMarkers(0);
+ // disable global edit mode
+ cy.toolbarButton('edit').click();
+
+ // there should be no markers anymore
+ cy.hasVertexMarkers(0);
+ });
+
+ it('enable continueDrawing', () => {
+ cy.window().then(({ map }) => {
+ map.pm.setGlobalOptions({ continueDrawing: true });
+ });
+
+ cy.toolbarButton('curve').click();
+
+ // draw a line with the curve tool
+
+ cy.get(mapSelector)
+ .click(150, 250)
+ .trigger('mousedown', 160, 50)
+ .trigger('mousemove', 250, 300)
+ .trigger('mousemove', 250, 300)
+ .trigger('mouseup')
+ .click(150, 250)
+
+ cy.get(mapSelector)
+ .click(300, 250)
+ .trigger('mousedown', 250, 50)
+ .trigger('mousemove', 300, 300)
+ .trigger('mousemove', 300, 300)
+ .trigger('mouseup')
+ .click(300, 250)
+
+ cy.toolbarButton('edit').click();
+ cy.hasVertexMarkers(6);
+ });
+
+
+ it('requireSnapToFinish', () => {
+ cy.window().then(({ map }) => {
+ map.pm.setGlobalOptions({
+ requireSnapToFinish: true,
+ snapSegment: false,
+ });
+ });
+
+ cy.toolbarButton('polygon').click();
+ cy.get(mapSelector)
+ .click(150, 250)
+ .click(160, 50)
+ .click(250, 50)
+ .click(150, 250);
+
+ cy.toolbarButton('curve').click();
+ cy.get(mapSelector).click(350, 250).click(300, 160).click(190, 60);
+
+ cy.window().then(({ map }) => {
+ map.pm.Draw.Curve._finishShape();
+ expect(1).to.eq(map.pm.getGeomanDrawLayers().length);
+ });
+
+ cy.get(mapSelector).click(250, 50);
+
+ cy.window().then(({ map }) => {
+ map.pm.Draw.Curve._finishShape();
+ expect(2).to.eq(map.pm.getGeomanDrawLayers().length);
+ });
+ });
+
+});
diff --git a/cypress/integration/polygon.spec.js b/cypress/integration/polygon.spec.js
index 8c428662..97cf6e5b 100644
--- a/cypress/integration/polygon.spec.js
+++ b/cypress/integration/polygon.spec.js
@@ -825,10 +825,10 @@ describe('Draw & Edit Poly', () => {
.click(150, 250);
cy.get(mapSelector)
- .click(230, 230)
+ .click(230, 250)
.click(250, 250)
.click(250, 300)
- .click(230, 230);
+ .click(230, 250);
cy.toolbarButton('edit').click();
cy.hasVertexMarkers(6);
diff --git a/cypress/integration/rectangle.spec.js b/cypress/integration/rectangle.spec.js
index d75911cc..681d461d 100644
--- a/cypress/integration/rectangle.spec.js
+++ b/cypress/integration/rectangle.spec.js
@@ -66,10 +66,10 @@ describe('Draw Rectangle', () => {
cy.toolbarButton('cut').click();
cy.get(mapSelector)
- .click(226, 389)
+ .click(226, 350)
.click(230, 105)
- .click(270, 396)
- .click(226, 389);
+ .click(270, 350)
+ .click(226, 350);
cy.toolbarButton('cut').click();
cy.get(mapSelector)
diff --git a/cypress/integration/toolbar.spec.js b/cypress/integration/toolbar.spec.js
index a1c9e87c..8b7fb331 100644
--- a/cypress/integration/toolbar.spec.js
+++ b/cypress/integration/toolbar.spec.js
@@ -326,7 +326,7 @@ describe('Testing the Toolbar', () => {
oneBlock: true,
});
cy.get('.leaflet-pm-toolbar.leaflet-pm-topleft').then((container) => {
- expect(container[0].children.length).to.equal(11);
+ expect(container[0].children.length).to.equal(12);
});
});
});
@@ -366,7 +366,7 @@ describe('Testing the Toolbar', () => {
title: 'Display text on hover button',
});
cy.get('.leaflet-pm-toolbar.leaflet-pm-topright').then((container) => {
- expect(container[0].children.length).to.equal(6);
+ expect(container[0].children.length).to.equal(7);
});
cy.get('.leaflet-pm-toolbar.leaflet-pm-topleft').then((container) => {
expect(container[0].children.length).to.equal(6);
diff --git a/cypress/support/commands.js b/cypress/support/commands.js
index d4fe5dbe..be62dae0 100644
--- a/cypress/support/commands.js
+++ b/cypress/support/commands.js
@@ -105,6 +105,12 @@ Cypress.Commands.add('hasVertexMarkers', (count) => {
});
});
+Cypress.Commands.add('hasHandleMarkers', (count) => {
+ cy.get('.marker-edit-handle').should(($p) => {
+ expect($p).to.have.length(count);
+ });
+});
+
Cypress.Commands.add('hasTotalVertexMarkers', (count) => {
cy.get('.marker-icon').should(($p) => {
expect($p).to.have.length(count);
diff --git a/demo/index.html b/demo/index.html
index 0c3d0a5d..cffb4f82 100644
--- a/demo/index.html
+++ b/demo/index.html
@@ -40,7 +40,8 @@ Editing A Layer Group
-
+
+
diff --git a/index.html b/index.html
index b557433e..3aec4dca 100644
--- a/index.html
+++ b/index.html
@@ -9,6 +9,7 @@
/>
+