diff --git a/externs/olx.js b/externs/olx.js index 09e1f63b39..c3fec4bade 100644 --- a/externs/olx.js +++ b/externs/olx.js @@ -2585,6 +2585,7 @@ olx.interaction.DragZoomOptions.prototype.out; * type: ol.geom.GeometryType, * maxPoints: (number|undefined), * minPoints: (number|undefined), + * finishCondition: (ol.events.ConditionType|undefined), * style: (ol.style.Style|Array.|ol.style.StyleFunction|undefined), * geometryFunction: (ol.interaction.DrawGeometryFunctionType|undefined), * geometryName: (string|undefined), @@ -2659,6 +2660,15 @@ olx.interaction.DrawOptions.prototype.maxPoints; olx.interaction.DrawOptions.prototype.minPoints; +/** + * A function that takes an {@link ol.MapBrowserEvent} and returns a boolean + * to indicate whether the drawing can be finished. + * @type {ol.events.ConditionType|undefined} + * @api + */ +olx.interaction.DrawOptions.prototype.finishCondition; + + /** * Style for sketch features. * @type {ol.style.Style|Array.|ol.style.StyleFunction|undefined} diff --git a/src/ol/interaction/drawinteraction.js b/src/ol/interaction/drawinteraction.js index 0b38d43c77..c6e5bce257 100644 --- a/src/ol/interaction/drawinteraction.js +++ b/src/ol/interaction/drawinteraction.js @@ -160,6 +160,13 @@ ol.interaction.Draw = function(options) { */ this.maxPoints_ = options.maxPoints ? options.maxPoints : Infinity; + /** + * A function to decide if a potential finish coordinate is permissable + * @private + * @type {ol.events.ConditionType} + */ + this.finishCondition_ = options.finishCondition ? options.finishCondition : goog.functions.TRUE; + var geometryFunction = options.geometryFunction; if (!geometryFunction) { if (this.type_ === ol.geom.GeometryType.CIRCLE) { @@ -404,7 +411,9 @@ ol.interaction.Draw.handleUpEvent_ = function(event) { } else if (this.mode_ === ol.interaction.DrawMode.CIRCLE) { this.finishDrawing(); } else if (this.atFinish_(event)) { - this.finishDrawing(); + if (this.finishCondition_(event)) { + this.finishDrawing(); + } } else { this.addToDrawing_(event); } diff --git a/test/spec/ol/interaction/drawinteraction.test.js b/test/spec/ol/interaction/drawinteraction.test.js index 1a491caddc..1925892958 100644 --- a/test/spec/ol/interaction/drawinteraction.test.js +++ b/test/spec/ol/interaction/drawinteraction.test.js @@ -333,6 +333,55 @@ describe('ol.interaction.Draw', function() { }); + describe('drawing with a finishCondition', function() { + beforeEach(function() { + var draw = new ol.interaction.Draw({ + source: source, + type: ol.geom.GeometryType.LINE_STRING, + finishCondition: function(event) { + if (ol.array.equals(event.coordinate,[30,-20])) { + return true; + } + return false; + } + }); + map.addInteraction(draw); + }); + + it('draws a linestring failing to finish it first, the finishes it', function() { + var features; + + // first point + simulateEvent('pointermove', 10, 20); + simulateEvent('pointerdown', 10, 20); + simulateEvent('pointerup', 10, 20); + + // second point + simulateEvent('pointermove', 40, 30); + simulateEvent('pointerdown', 40, 30); + simulateEvent('pointerup', 40, 30); + + // try to finish on this point + simulateEvent('pointerdown', 40, 30); + simulateEvent('pointerup', 40, 30); + + features = source.getFeatures(); + expect(features).to.have.length(0); + + // third point + simulateEvent('pointermove', 30, 20); + simulateEvent('pointerdown', 30, 20); + simulateEvent('pointerup', 30, 20); + + // finish on this point + simulateEvent('pointerdown', 30, 20); + simulateEvent('pointerup', 30, 20); + + features = source.getFeatures(); + expect(features).to.have.length(1); + }); + }); + describe('drawing multi-linestrings', function() { beforeEach(function() { @@ -811,6 +860,7 @@ describe('ol.interaction.Draw', function() { }); }); +goog.require('ol.array'); goog.require('ol.events'); goog.require('ol.Feature'); goog.require('ol.Map');