diff --git a/examples/dragzoom.html b/examples/dragzoom.html new file mode 100644 index 0000000000..0cd64bb6c1 --- /dev/null +++ b/examples/dragzoom.html @@ -0,0 +1,51 @@ + + + + + + + + + + + DragZoom example + + + + + +
+ +
+
+
+
+
+ +
+ +
+

DragZoom example

+

Example of dragzoom interaction

+
+

See the dragzoom.js source to see how this is done.

+

For the moment, only works with the canvas renderer.

+
+
dragzoom, openstreetmap
+
+ +
+ +
+ + + + + + diff --git a/examples/dragzoom.js b/examples/dragzoom.js new file mode 100644 index 0000000000..86d83114d4 --- /dev/null +++ b/examples/dragzoom.js @@ -0,0 +1,24 @@ +goog.require('ol.Map'); +goog.require('ol.RendererHint'); +goog.require('ol.View2D'); +goog.require('ol.interaction.DragZoom'); +goog.require('ol.layer.Tile'); +goog.require('ol.source.OSM'); + + +var map = new ol.Map({ + layers: [ + new ol.layer.Tile({ + source: new ol.source.OSM() + }) + ], + renderer: ol.RendererHint.CANVAS, + target: 'map', + view: new ol.View2D({ + center: [0, 0], + zoom: 2 + }) +}); + +var dragzoom = new ol.interaction.DragZoom(); +map.addInteraction(dragzoom); diff --git a/src/objectliterals.jsdoc b/src/objectliterals.jsdoc index 8c6ea96f23..ea3509e0cb 100644 --- a/src/objectliterals.jsdoc +++ b/src/objectliterals.jsdoc @@ -312,11 +312,21 @@ * @todo stability experimental */ +/** + * @typedef {Object} olx.interaction.DragBoxOptions + * @property {ol.events.ConditionType|undefined} condition A conditional + * modifier (i.e. Shift key) that determines if the interaction is active + * or not, default is always. + * @property {ol.style.Style} style Style for the box. + * @todo stability experimental + */ + /** * @typedef {Object} olx.interaction.DragZoomOptions * @property {ol.events.ConditionType|undefined} condition A conditional * modifier (i.e. Shift key) that determines if the interaction is active * or not, default is shift key. + * @property {ol.style.Style} style Style for the box. * @todo stability experimental */ @@ -332,8 +342,6 @@ * desired. Default is `true`. * @property {boolean|undefined} mouseWheelZoom Whether mousewheel zoom is * desired. Default is `true`. - * @property {boolean|undefined} shiftDragZoom Whether Shift-drag zoom is - * desired. Default is `true`. * @property {boolean|undefined} touchPan Whether touch pan is * desired. Default is `true`. * @property {boolean|undefined} touchRotate Whether touch rotate is desired. Default is `true`. diff --git a/src/ol/interaction/dragboxinteraction.exports b/src/ol/interaction/dragboxinteraction.exports new file mode 100644 index 0000000000..bb21d81015 --- /dev/null +++ b/src/ol/interaction/dragboxinteraction.exports @@ -0,0 +1,5 @@ +@exportSymbol ol.interaction.DragBox +@exportProperty ol.interaction.DragBox.prototype.getGeometry + +@exportSymbol ol.DragBoxEvent +@exportProperty ol.DragBoxEvent.prototype.getCoordinate diff --git a/src/ol/interaction/dragboxinteraction.js b/src/ol/interaction/dragboxinteraction.js new file mode 100644 index 0000000000..d50d887838 --- /dev/null +++ b/src/ol/interaction/dragboxinteraction.js @@ -0,0 +1,161 @@ +// FIXME draw drag box +// FIXME works for View2D only + +goog.provide('ol.DragBoxEvent'); +goog.provide('ol.interaction.DragBox'); + +goog.require('goog.asserts'); +goog.require('goog.events.Event'); +goog.require('ol.events.ConditionType'); +goog.require('ol.events.condition'); +goog.require('ol.interaction.Drag'); +goog.require('ol.render.Box'); + + +/** + * @define {number} Hysterisis pixels. + */ +ol.DRAG_BOX_HYSTERESIS_PIXELS = 8; + + +/** + * @const {number} + */ +ol.DRAG_BOX_HYSTERESIS_PIXELS_SQUARED = + ol.DRAG_BOX_HYSTERESIS_PIXELS * + ol.DRAG_BOX_HYSTERESIS_PIXELS; + + +/** + * @enum {string} + */ +ol.DragBoxEventType = { + BOXSTART: 'boxstart', + BOXEND: 'boxend' +}; + + + +/** + * Object representing a dragbox event. + * + * @param {string} type The event type. + * @param {ol.Coordinate} coordinate The event coordinate. + * @extends {goog.events.Event} + * @constructor + */ +ol.DragBoxEvent = function(type, coordinate) { + goog.base(this, type); + + /** + * The coordinate of the drag event. + * @type {ol.Coordinate} + * @private + */ + this.coordinate_ = coordinate; + +}; +goog.inherits(ol.DragBoxEvent, goog.events.Event); + + +/** + * Get the name of the property associated with this event. + * @return {ol.Coordinate} Event coordinate. + */ +ol.DragBoxEvent.prototype.getCoordinate = function() { + return this.coordinate_; +}; + + + +/** + * @constructor + * @extends {ol.interaction.Drag} + * @param {olx.interaction.DragBoxOptions=} opt_options Options. + * @todo stability experimental + */ +ol.interaction.DragBox = function(opt_options) { + + goog.base(this); + + var options = goog.isDef(opt_options) ? opt_options : {}; + + /** + * @private + * @type {ol.style.Style} + */ + var style = goog.isDef(options.style) ? options.style : null; + + /** + * @type {ol.render.Box} + * @private + */ + this.box_ = new ol.render.Box(style); + + /** + * @private + * @type {ol.events.ConditionType} + */ + this.condition_ = goog.isDef(options.condition) ? + options.condition : ol.events.condition.always; + +}; +goog.inherits(ol.interaction.DragBox, ol.interaction.Drag); + + +/** + * @inheritDoc + */ +ol.interaction.DragBox.prototype.handleDrag = function(mapBrowserEvent) { + this.box_.setCoordinates( + this.startCoordinate, mapBrowserEvent.getCoordinate()); +}; + + +/** + * Returns geometry of last drawn box. + * @return {ol.geom.Geometry} Geometry. + */ +ol.interaction.DragBox.prototype.getGeometry = function() { + return this.box_.getGeometry(); +}; + + +/** + * To be overriden by child classes. + * @protected + */ +ol.interaction.DragBox.prototype.onBoxEnd = goog.nullFunction; + + +/** + * @inheritDoc + */ +ol.interaction.DragBox.prototype.handleDragEnd = + function(mapBrowserEvent) { + this.box_.setMap(null); + if (this.deltaX * this.deltaX + this.deltaY * this.deltaY >= + ol.DRAG_BOX_HYSTERESIS_PIXELS_SQUARED) { + this.onBoxEnd(mapBrowserEvent); + this.dispatchEvent(new ol.DragBoxEvent(ol.DragBoxEventType.BOXEND, + mapBrowserEvent.getCoordinate())); + } +}; + + +/** + * @inheritDoc + */ +ol.interaction.DragBox.prototype.handleDragStart = + function(mapBrowserEvent) { + var browserEvent = mapBrowserEvent.browserEvent; + if (browserEvent.isMouseActionButton() && this.condition_(mapBrowserEvent)) { + this.box_.setCoordinates(this.startCoordinate, this.startCoordinate); + this.box_.setMap(mapBrowserEvent.map); + this.dispatchEvent(new ol.DragBoxEvent(ol.DragBoxEventType.BOXSTART, + mapBrowserEvent.getCoordinate())); + return true; + } else { + return false; + } +}; diff --git a/src/ol/interaction/dragzoom.exports b/src/ol/interaction/dragzoominteraction.exports similarity index 100% rename from src/ol/interaction/dragzoom.exports rename to src/ol/interaction/dragzoominteraction.exports diff --git a/src/ol/interaction/dragzoominteraction.js b/src/ol/interaction/dragzoominteraction.js index b7a6737613..64c7e959ef 100644 --- a/src/ol/interaction/dragzoominteraction.js +++ b/src/ol/interaction/dragzoominteraction.js @@ -1,30 +1,10 @@ -// FIXME draw drag box -// FIXME works for View2D only - goog.provide('ol.interaction.DragZoom'); goog.require('goog.asserts'); -goog.require('ol.Size'); -goog.require('ol.View2D'); -goog.require('ol.events.ConditionType'); goog.require('ol.events.condition'); -goog.require('ol.extent'); -goog.require('ol.interaction.Drag'); -goog.require('ol.render.DragBox'); - - -/** - * @define {number} Hysterisis pixels. - */ -ol.SHIFT_DRAG_ZOOM_HYSTERESIS_PIXELS = 8; - - -/** - * @const {number} - */ -ol.SHIFT_DRAG_ZOOM_HYSTERESIS_PIXELS_SQUARED = - ol.SHIFT_DRAG_ZOOM_HYSTERESIS_PIXELS * - ol.SHIFT_DRAG_ZOOM_HYSTERESIS_PIXELS; +goog.require('ol.interaction.DragBox'); +goog.require('ol.style.Stroke'); +goog.require('ol.style.Style'); @@ -33,77 +13,46 @@ ol.SHIFT_DRAG_ZOOM_HYSTERESIS_PIXELS_SQUARED = * normally combined with an {@link ol.events.condition} that limits * it to when the shift key is held down. * @constructor - * @extends {ol.interaction.Drag} + * @extends {ol.interaction.DragBox} * @param {olx.interaction.DragZoomOptions=} opt_options Options. * @todo stability experimental */ ol.interaction.DragZoom = function(opt_options) { - - goog.base(this); - var options = goog.isDef(opt_options) ? opt_options : {}; - /** - * @private - * @type {ol.events.ConditionType} - */ - this.condition_ = goog.isDef(options.condition) ? + var condition = goog.isDef(options.condition) ? options.condition : ol.events.condition.shiftKeyOnly; /** - * @type {ol.render.DragBox} * @private + * @type {ol.style.Style} */ - this.dragBox_ = new ol.render.DragBox(); + var style = goog.isDef(options.style) ? + options.style : new ol.style.Style({ + stroke: new ol.style.Stroke({ + color: 'blue' + }) + }); + + goog.base(this, { + condition: condition, + style: style + }); }; -goog.inherits(ol.interaction.DragZoom, ol.interaction.Drag); +goog.inherits(ol.interaction.DragZoom, ol.interaction.DragBox); /** * @inheritDoc */ -ol.interaction.DragZoom.prototype.handleDrag = function(mapBrowserEvent) { - this.dragBox_.setCoordinates( - this.startCoordinate, mapBrowserEvent.getCoordinate()); -}; - - -/** - * @inheritDoc - */ -ol.interaction.DragZoom.prototype.handleDragEnd = - function(mapBrowserEvent) { - this.dragBox_.setMap(null); - if (this.deltaX * this.deltaX + this.deltaY * this.deltaY >= - ol.SHIFT_DRAG_ZOOM_HYSTERESIS_PIXELS_SQUARED) { - var map = mapBrowserEvent.map; - var extent = ol.extent.boundingExtent( - [this.startCoordinate, mapBrowserEvent.getCoordinate()]); - map.withFrozenRendering(function() { - // FIXME works for View2D only - var view = map.getView(); - goog.asserts.assertInstanceof(view, ol.View2D); - var mapSize = /** @type {ol.Size} */ (map.getSize()); - view.fitExtent(extent, mapSize); - // FIXME we should preserve rotation - view.setRotation(0); - }); - } -}; - - -/** - * @inheritDoc - */ -ol.interaction.DragZoom.prototype.handleDragStart = - function(mapBrowserEvent) { - var browserEvent = mapBrowserEvent.browserEvent; - if (browserEvent.isMouseActionButton() && this.condition_(mapBrowserEvent)) { - this.dragBox_.setCoordinates(this.startCoordinate, this.startCoordinate); - this.dragBox_.setMap(mapBrowserEvent.map); - return true; - } else { - return false; - } +ol.interaction.DragZoom.prototype.onBoxEnd = function() { + this.getMap().withFrozenRendering(goog.bind(function() { + // FIXME works for View2D only + var view = this.getMap().getView().getView2D(); + + view.fitExtent(this.getGeometry().getExtent(), this.getMap().getSize()); + // FIXME we should preserve rotation + view.setRotation(0); + }, this)); }; diff --git a/src/ol/interaction/interactiondefaults.js b/src/ol/interaction/interactiondefaults.js index 32b4e5569c..b664e24edb 100644 --- a/src/ol/interaction/interactiondefaults.js +++ b/src/ol/interaction/interactiondefaults.js @@ -5,7 +5,6 @@ goog.require('ol.Kinetic'); goog.require('ol.interaction.DoubleClickZoom'); goog.require('ol.interaction.DragPan'); goog.require('ol.interaction.DragRotate'); -goog.require('ol.interaction.DragZoom'); goog.require('ol.interaction.KeyboardPan'); goog.require('ol.interaction.KeyboardZoom'); goog.require('ol.interaction.MouseWheelZoom'); @@ -99,12 +98,6 @@ ol.interaction.defaults = function(opt_options) { })); } - var shiftDragZoom = goog.isDef(options.shiftDragZoom) ? - options.shiftDragZoom : true; - if (shiftDragZoom) { - interactions.push(new ol.interaction.DragZoom()); - } - return interactions; }; diff --git a/src/ol/render/dragbox.js b/src/ol/render/box.js similarity index 56% rename from src/ol/render/dragbox.js rename to src/ol/render/box.js index 80e938a0c8..5e728073e4 100644 --- a/src/ol/render/dragbox.js +++ b/src/ol/render/box.js @@ -1,22 +1,21 @@ // FIXME add rotation -goog.provide('ol.render.DragBox'); +goog.provide('ol.render.Box'); goog.require('goog.Disposable'); +goog.require('goog.asserts'); goog.require('goog.events'); goog.require('ol.geom.Polygon'); goog.require('ol.render.EventType'); -goog.require('ol.style.Fill'); -goog.require('ol.style.Style'); /** * @constructor * @extends {goog.Disposable} - * @param {ol.style.Style=} opt_style Style. + * @param {ol.style.Style} style Style. */ -ol.render.DragBox = function(opt_style) { +ol.render.Box = function(style) { /** * @private @@ -26,9 +25,9 @@ ol.render.DragBox = function(opt_style) { /** * @private - * @type {goog.events.Key|undefined} + * @type {goog.events.Key} */ - this.postComposeListenKey_ = undefined; + this.postComposeListenerKey_ = null; /** * @private @@ -42,28 +41,47 @@ ol.render.DragBox = function(opt_style) { */ this.endCoordinate_ = null; + /** + * @private + * @type {ol.geom.Polygon} + */ + this.geometry_ = null; + /** * @private * @type {ol.style.Style} */ - this.style_ = goog.isDef(opt_style) ? opt_style : new ol.style.Style({ - fill: new ol.style.Fill({ - color: 'rgba(0,0,0,0.5)' - }), - image: null, - stroke: null, - text: null, - zIndex: 0 - }); + this.style_ = style; }; -goog.inherits(ol.render.DragBox, goog.Disposable); +goog.inherits(ol.render.Box, goog.Disposable); + + +/** + * @private + * @return {ol.geom.Polygon} Geometry. + */ +ol.render.Box.prototype.createGeometry_ = function() { + goog.asserts.assert(!goog.isNull(this.startCoordinate_)); + goog.asserts.assert(!goog.isNull(this.endCoordinate_)); + var startCoordinate = this.startCoordinate_; + var endCoordinate = this.endCoordinate_; + var coordinates = [ + [ + startCoordinate, + [startCoordinate[0], endCoordinate[1]], + endCoordinate, + [endCoordinate[0], startCoordinate[1]] + ] + ]; + return new ol.geom.Polygon(coordinates); +}; /** * @inheritDoc */ -ol.render.DragBox.prototype.disposeInternal = function() { +ol.render.Box.prototype.disposeInternal = function() { this.setMap(null); }; @@ -72,39 +90,28 @@ ol.render.DragBox.prototype.disposeInternal = function() { * @param {ol.render.Event} event Event. * @private */ -ol.render.DragBox.prototype.handleMapPostCompose_ = function(event) { - var render = event.getRender(); - var startCoordinate = this.startCoordinate_; - var endCoordinate = this.endCoordinate_; - - var extent = event.getFrameState().extent; - var coordinates = [ - // outer ring - [ - [extent[0], extent[1]], - [extent[0], extent[3]], - [extent[2], extent[3]], - [extent[2], extent[1]] - ], - // inner ring - [ - startCoordinate, - [startCoordinate[0], endCoordinate[1]], - endCoordinate, - [endCoordinate[0], startCoordinate[1]] - ] - ]; - var geometry = new ol.geom.Polygon(coordinates); +ol.render.Box.prototype.handleMapPostCompose_ = function(event) { + this.geometry_ = this.createGeometry_(); var style = this.style_; + goog.asserts.assert(!goog.isNull(style)); + var render = event.getRender(); render.setFillStrokeStyle(style.getFill(), style.getStroke()); - render.drawPolygonGeometry(geometry, null); + render.drawPolygonGeometry(this.geometry_, null); +}; + + +/** + * @return {ol.geom.Polygon} Geometry. + */ +ol.render.Box.prototype.getGeometry = function() { + return this.geometry_; }; /** * @private */ -ol.render.DragBox.prototype.requestMapRenderFrame_ = function() { +ol.render.Box.prototype.requestMapRenderFrame_ = function() { if (!goog.isNull(this.map_) && !goog.isNull(this.startCoordinate_) && !goog.isNull(this.endCoordinate_)) { @@ -116,16 +123,16 @@ ol.render.DragBox.prototype.requestMapRenderFrame_ = function() { /** * @param {ol.Map} map Map. */ -ol.render.DragBox.prototype.setMap = function(map) { - if (goog.isDef(this.postComposeListenKey_)) { - goog.events.unlistenByKey(this.postComposeListenKey_); - this.postComposeListenKey_ = undefined; +ol.render.Box.prototype.setMap = function(map) { + if (!goog.isNull(this.postComposeListenerKey_)) { + goog.events.unlistenByKey(this.postComposeListenerKey_); + this.postComposeListenerKey_ = null; this.map_.requestRenderFrame(); this.map_ = null; } this.map_ = map; if (!goog.isNull(this.map_)) { - this.postComposeListenKey_ = goog.events.listen( + this.postComposeListenerKey_ = goog.events.listen( map, ol.render.EventType.POSTCOMPOSE, this.handleMapPostCompose_, false, this); this.requestMapRenderFrame_(); @@ -137,7 +144,7 @@ ol.render.DragBox.prototype.setMap = function(map) { * @param {ol.Coordinate} startCoordinate Start coordinate. * @param {ol.Coordinate} endCoordinate End coordinate. */ -ol.render.DragBox.prototype.setCoordinates = +ol.render.Box.prototype.setCoordinates = function(startCoordinate, endCoordinate) { this.startCoordinate_ = startCoordinate; this.endCoordinate_ = endCoordinate; diff --git a/src/ol/render/dragbox.exports b/src/ol/render/dragbox.exports deleted file mode 100644 index c98c668fb9..0000000000 --- a/src/ol/render/dragbox.exports +++ /dev/null @@ -1,3 +0,0 @@ -@exportSymbol ol.render.DragBox -@exportProperty ol.render.DragBox.prototype.setCoordinates -@exportProperty ol.render.DragBox.prototype.setMap