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 @@ /> +