diff --git a/examples/modify-test.js b/examples/modify-test.js index 5c28dec341..0b7c31bf7f 100644 --- a/examples/modify-test.js +++ b/examples/modify-test.js @@ -222,7 +222,13 @@ var select = new ol.interaction.Select({ var modify = new ol.interaction.Modify({ features: select.getFeatures(), - style: overlayStyle + style: overlayStyle, + insertVertexCondition: function() { + // prevent new vertices to be added to the polygons + return !this.features_.getArray().every(function(feature) { + return feature.getGeometry().getType().match(/Polygon/); + }); + } }); var map = new ol.Map({ diff --git a/externs/olx.js b/externs/olx.js index a47e678e71..92e0314713 100644 --- a/externs/olx.js +++ b/externs/olx.js @@ -3164,12 +3164,15 @@ olx.interaction.KeyboardZoomOptions.prototype.delta; /** - * @typedef {{condition: (ol.EventsConditionType|undefined), + * @typedef {{ + * condition: (ol.EventsConditionType|undefined), * deleteCondition: (ol.EventsConditionType|undefined), + * insertVertexCondition: (ol.EventsConditionType|undefined), * pixelTolerance: (number|undefined), * style: (ol.style.Style|Array.|ol.StyleFunction|undefined), * features: ol.Collection., - * wrapX: (boolean|undefined)}} + * wrapX: (boolean|undefined) + * }} */ olx.interaction.ModifyOptions; @@ -3196,6 +3199,16 @@ olx.interaction.ModifyOptions.prototype.condition; olx.interaction.ModifyOptions.prototype.deleteCondition; +/** + * A function that takes an {@link ol.MapBrowserEvent} and returns a boolean + * to indicate whether a new vertex can be added to the sketch features. + * Default is {@link ol.events.condition.always} + * @type {ol.EventsConditionType|undefined} + * @api + */ +olx.interaction.ModifyOptions.prototype.insertVertexCondition; + + /** * Pixel tolerance for considering the pointer close enough to a segment or * vertex for editing. Default is `10`. diff --git a/src/ol/interaction/modify.js b/src/ol/interaction/modify.js index b9113451cd..54b9b79afe 100644 --- a/src/ol/interaction/modify.js +++ b/src/ol/interaction/modify.js @@ -67,6 +67,13 @@ ol.interaction.Modify = function(options) { this.deleteCondition_ = options.deleteCondition ? options.deleteCondition : this.defaultDeleteCondition_; + /** + * @type {ol.EventsConditionType} + * @private + */ + this.insertVertexCondition_ = options.insertVertexCondition ? + options.insertVertexCondition : ol.events.condition.always; + /** * Editing vertex. * @type {ol.Feature} @@ -600,7 +607,7 @@ ol.interaction.Modify.handleDownEvent_ = function(evt) { this.dragSegments_.push([segmentDataMatch, 1]); componentSegments[uid][1] = segmentDataMatch; - } else if (ol.getUid(segment) in this.vertexSegments_ && + } else if (this.insertVertexCondition_(evt) && ol.getUid(segment) in this.vertexSegments_ && (!componentSegments[uid][0] && !componentSegments[uid][1])) { insertVertices.push([segmentDataMatch, vertex]); } diff --git a/test/spec/ol/interaction/modify.test.js b/test/spec/ol/interaction/modify.test.js index 8ab79812b3..f22a10a9da 100644 --- a/test/spec/ol/interaction/modify.test.js +++ b/test/spec/ol/interaction/modify.test.js @@ -559,6 +559,40 @@ describe('ol.interaction.Modify', function() { }); }); + describe('insertVertexCondition', function() { + it('calls the callback function', function() { + var listenerSpy = sinon.spy(function(event) { + return false; + }); + + var modify = new ol.interaction.Modify({ + features: new ol.Collection(features), + insertVertexCondition: listenerSpy + }); + map.addInteraction(modify); + var feature = features[0]; + + // move first vertex + simulateEvent('pointermove', 0, 0, false, 0); + simulateEvent('pointerdown', 0, 0, false, 0); + simulateEvent('pointermove', -10, -10, false, 0); + simulateEvent('pointerdrag', -10, -10, false, 0); + simulateEvent('pointerup', -10, -10, false, 0); + + expect(listenerSpy.callCount).to.be(0); + expect(feature.getGeometry().getCoordinates()[0]).to.have.length(5); + + // try to add vertex + simulateEvent('pointerdown', 40, -20, false, 0); + simulateEvent('pointerup', 40, -20, false, 0); + simulateEvent('click', 40, -20, false, 0); + simulateEvent('singleclick', 40, -20, false, 0); + + expect(listenerSpy.callCount).to.be(1); + expect(feature.getGeometry().getCoordinates()[0]).to.have.length(5); + }); + }); + describe('handle feature change', function() { var getListeners;