diff --git a/src/ol/interaction/Modify.js b/src/ol/interaction/Modify.js index 58b6178553..4a20d3665f 100644 --- a/src/ol/interaction/Modify.js +++ b/src/ol/interaction/Modify.js @@ -128,6 +128,9 @@ const ModifyEventType = { * provided, a vector source must be provided with the `source` option. * @property {boolean} [wrapX=false] Wrap the world horizontally on the sketch * overlay. + * @property {boolean} [snapToPointer=false] The vertex, point or segment being modified snaps to the + * pointer coordinate when clicked within the `pixelTolerance`. Setting this to `true` is recommended + * when the `Snap` interaction is used and the source geometry is not a snap target. */ /** @@ -386,6 +389,11 @@ class Modify extends PointerInteraction { * @type {Array} */ this.delta_ = [0, 0]; + + /** + * @private + */ + this.snapToPointer_ = options.snapToPointer || false; } /** @@ -1163,8 +1171,10 @@ class Modify extends PointerInteraction { const vertexSegments = {}; vertexSegments[getUid(closestSegment)] = true; - this.delta_[0] = vertex[0] - pixelCoordinate[0]; - this.delta_[1] = vertex[1] - pixelCoordinate[1]; + if (!this.snapToPointer_) { + this.delta_[0] = vertex[0] - pixelCoordinate[0]; + this.delta_[1] = vertex[1] - pixelCoordinate[1]; + } if ( node.geometry.getType() === GeometryType.CIRCLE && node.index === CIRCLE_CIRCUMFERENCE_INDEX diff --git a/test/spec/ol/interaction/modify.test.js b/test/spec/ol/interaction/modify.test.js index f6387f5b57..e25e8b5c67 100644 --- a/test/spec/ol/interaction/modify.test.js +++ b/test/spec/ol/interaction/modify.test.js @@ -208,6 +208,11 @@ describe('ol.interaction.Modify', function () { expect(rbushEntries[0].feature).to.be(feature); expect(modify.hitDetection_).to.be(layer); }); + + it('accepts a snapToPointer option', function () { + const modify = new Modify({source: source, snapToPointer: true}); + expect(modify.snapToPointer_).to.be(true); + }); }); describe('vertex deletion', function () { @@ -1039,6 +1044,37 @@ describe('ol.interaction.Modify', function () { pointFeature.getGeometry() ); }); + + it('snaps to pointer when snapToPointer is true', function () { + const modify = new Modify({ + snapToPointer: true, + source: source, + }); + map.addInteraction(modify); + source.clear(); + const pointFeature = new Feature(new Point([0, 0])); + source.addFeature(pointFeature); + map.renderSync(); + simulateEvent('pointerdown', 2, 2, null, 0); + simulateEvent('pointerdrag', 2, 2, null, 0); + simulateEvent('pointerup', 2, 2, null, 0); + expect(pointFeature.getGeometry().getCoordinates()).to.eql([2, -2]); + }); + + it('does not snap to pointer by default', function () { + const modify = new Modify({ + source: source, + }); + map.addInteraction(modify); + source.clear(); + const pointFeature = new Feature(new Point([0, 0])); + source.addFeature(pointFeature); + map.renderSync(); + simulateEvent('pointerdown', 2, 2, null, 0); + simulateEvent('pointerdrag', 2, 2, null, 0); + simulateEvent('pointerup', 2, 2, null, 0); + expect(pointFeature.getGeometry().getCoordinates()).to.eql([0, 0]); + }); }); describe('#getOverlay', function () {