diff --git a/changelog/upgrade-notes.md b/changelog/upgrade-notes.md index 083d7dc21f..52af5ea650 100644 --- a/changelog/upgrade-notes.md +++ b/changelog/upgrade-notes.md @@ -93,6 +93,10 @@ var tileUrlFunction = function(tileCoord, pixelRatio, projection) { The replacement of `ol.tilegrid.Zoomify` is a plain `ol.tilegrid.TileGrid`, configured with `extent`, `origin` and `resolutions`. If the `size` passed to the `ol.source.Zoomify` source is `[width, height]`, then the extent for the tile grid will be `[0, -height, width, 0]`, and the origin will be `[0, 0]`. +#### Replace `ol.View.fitExtent()` and `ol.View.fitGeometry()` with `ol.View.fit()` +* This combines two previously distinct functions into one more flexible call which takes either a geometry or an extent. +* Rename all calls to `fitExtent` and `fitGeometry` to `fit`. + ### v3.6.0 #### `ol.interaction.Draw` changes diff --git a/examples/center.html b/examples/center.html index 0b90d3cf0c..b70b106152 100644 --- a/examples/center.html +++ b/examples/center.html @@ -6,7 +6,7 @@ docs: > This example demonstrates how a map's view can be adjusted so a geometry or coordinate is positioned at a specific pixel location. The map above has top, right, bottom, and left - padding applied inside the viewport. The view's fitGeometry method + padding applied inside the viewport. The view's fit method is used to fit a geometry in the view with the same padding. The view's centerOn method is used to position a coordinate (Lausanne) at a specific pixel location (the center of the black box). diff --git a/examples/center.js b/examples/center.js index c154b19ebf..1392aee78f 100644 --- a/examples/center.js +++ b/examples/center.js @@ -65,7 +65,7 @@ zoomtoswitzerlandbest.addEventListener('click', function() { var feature = source.getFeatures()[0]; var polygon = /** @type {ol.geom.SimpleGeometry} */ (feature.getGeometry()); var size = /** @type {ol.Size} */ (map.getSize()); - view.fitGeometry( + view.fit( polygon, size, { @@ -81,7 +81,7 @@ zoomtoswitzerlandconstrained.addEventListener('click', function() { var feature = source.getFeatures()[0]; var polygon = /** @type {ol.geom.SimpleGeometry} */ (feature.getGeometry()); var size = /** @type {ol.Size} */ (map.getSize()); - view.fitGeometry( + view.fit( polygon, size, { @@ -96,7 +96,7 @@ zoomtoswitzerlandnearest.addEventListener('click', function() { var feature = source.getFeatures()[0]; var polygon = /** @type {ol.geom.SimpleGeometry} */ (feature.getGeometry()); var size = /** @type {ol.Size} */ (map.getSize()); - view.fitGeometry( + view.fit( polygon, size, { @@ -111,7 +111,7 @@ zoomtolausanne.addEventListener('click', function() { var feature = source.getFeatures()[1]; var point = /** @type {ol.geom.SimpleGeometry} */ (feature.getGeometry()); var size = /** @type {ol.Size} */ (map.getSize()); - view.fitGeometry( + view.fit( point, size, { diff --git a/examples/drag-and-drop-image-vector.js b/examples/drag-and-drop-image-vector.js index 5a01905620..87111e1b06 100644 --- a/examples/drag-and-drop-image-vector.js +++ b/examples/drag-and-drop-image-vector.js @@ -122,7 +122,7 @@ dragAndDropInteraction.on('addfeatures', function(event) { style: styleFunction }) })); - map.getView().fitExtent( + map.getView().fit( vectorSource.getExtent(), /** @type {ol.Size} */ (map.getSize())); }); diff --git a/examples/drag-and-drop.js b/examples/drag-and-drop.js index 8a00de3f15..93942597bd 100644 --- a/examples/drag-and-drop.js +++ b/examples/drag-and-drop.js @@ -118,7 +118,7 @@ dragAndDropInteraction.on('addfeatures', function(event) { source: vectorSource, style: styleFunction })); - map.getView().fitExtent( + map.getView().fit( vectorSource.getExtent(), /** @type {ol.Size} */ (map.getSize())); }); diff --git a/externs/olx.js b/externs/olx.js index 11b2e991b9..1bcc8694a8 100644 --- a/externs/olx.js +++ b/externs/olx.js @@ -1,3 +1,4 @@ + /** * @type {Object} */ @@ -6406,7 +6407,7 @@ olx.view; * minResolution: (number|undefined)}} * @api */ -olx.view.FitGeometryOptions; +olx.view.FitOptions; /** @@ -6415,7 +6416,7 @@ olx.view.FitGeometryOptions; * @type {!Array.} * @api */ -olx.view.FitGeometryOptions.prototype.padding; +olx.view.FitOptions.prototype.padding; /** @@ -6423,7 +6424,7 @@ olx.view.FitGeometryOptions.prototype.padding; * @type {boolean|undefined} * @api */ -olx.view.FitGeometryOptions.prototype.constrainResolution; +olx.view.FitOptions.prototype.constrainResolution; /** @@ -6431,7 +6432,7 @@ olx.view.FitGeometryOptions.prototype.constrainResolution; * @type {boolean|undefined} * @api */ -olx.view.FitGeometryOptions.prototype.nearest; +olx.view.FitOptions.prototype.nearest; /** @@ -6439,7 +6440,7 @@ olx.view.FitGeometryOptions.prototype.nearest; * @type {number|undefined} * @api */ -olx.view.FitGeometryOptions.prototype.minResolution; +olx.view.FitOptions.prototype.minResolution; /** @@ -6448,7 +6449,7 @@ olx.view.FitGeometryOptions.prototype.minResolution; * @type {number|undefined} * @api */ -olx.view.FitGeometryOptions.prototype.maxZoom; +olx.view.FitOptions.prototype.maxZoom; /* typedefs for object literals exposed by the library */ diff --git a/src/ol/control/overviewmapcontrol.js b/src/ol/control/overviewmapcontrol.js index 0e883cc9c0..6a85934105 100644 --- a/src/ol/control/overviewmapcontrol.js +++ b/src/ol/control/overviewmapcontrol.js @@ -338,7 +338,7 @@ ol.control.OverviewMap.prototype.resetExtent_ = function() { ol.OVERVIEWMAP_MAX_RATIO / ol.OVERVIEWMAP_MIN_RATIO) / Math.LN2; var ratio = 1 / (Math.pow(2, steps / 2) * ol.OVERVIEWMAP_MIN_RATIO); ol.extent.scaleFromCenter(extent, ratio); - ovview.fitExtent(extent, ovmapSize); + ovview.fit(extent, ovmapSize); }; diff --git a/src/ol/control/zoomtoextentcontrol.js b/src/ol/control/zoomtoextentcontrol.js index 6499d786fd..6bb37f65b1 100644 --- a/src/ol/control/zoomtoextentcontrol.js +++ b/src/ol/control/zoomtoextentcontrol.js @@ -77,5 +77,5 @@ ol.control.ZoomToExtent.prototype.handleZoomToExtent_ = function() { view.getProjection().getExtent() : this.extent_; var size = map.getSize(); goog.asserts.assert(goog.isDef(size), 'size should be defined'); - view.fitExtent(extent, size); + view.fit(extent, size); }; diff --git a/src/ol/view.js b/src/ol/view.js index 4b2b50cfe4..db4dd8a79f 100644 --- a/src/ol/view.js +++ b/src/ol/view.js @@ -14,6 +14,8 @@ goog.require('ol.RotationConstraintType'); goog.require('ol.Size'); goog.require('ol.coordinate'); goog.require('ol.extent'); +goog.require('ol.geom.Polygon'); +goog.require('ol.geom.SimpleGeometry'); goog.require('ol.proj'); goog.require('ol.proj.METERS_PER_UNIT'); goog.require('ol.proj.Projection'); @@ -273,15 +275,17 @@ ol.View.prototype.getHints = function() { * @api stable */ ol.View.prototype.calculateExtent = function(size) { - goog.asserts.assert(this.isDef(), - 'the view was not defined (had no center and/or resolution)'); var center = this.getCenter(); + goog.asserts.assert(goog.isDefAndNotNull(center), + 'The view center is not defined'); var resolution = this.getResolution(); - var minX = center[0] - resolution * size[0] / 2; - var maxX = center[0] + resolution * size[0] / 2; - var minY = center[1] - resolution * size[1] / 2; - var maxY = center[1] + resolution * size[1] / 2; - return [minX, minY, maxX, maxY]; + goog.asserts.assert(goog.isDef(resolution), + 'The view resolution is not defined'); + var rotation = this.getRotation(); + goog.asserts.assert(goog.isDef(rotation), + 'The view rotation is not defined'); + + return ol.extent.getForViewAndSize(center, resolution, rotation, size); }; @@ -431,35 +435,24 @@ ol.View.prototype.getZoom = function() { /** - * Fit the map view to the passed extent and size. The size is pixel dimensions - * of the box to fit the extent into. In most cases you will want to use the map - * size, that is `map.getSize()`. - * @param {ol.Extent} extent Extent. + * Fit the given geometry or extent based on the given map size and border. + * The size is pixel dimensions of the box to fit the extent into. + * In most cases you will want to use the map size, that is `map.getSize()`. + * Takes care of the map angle. + * @param {ol.geom.SimpleGeometry|ol.Extent} geometry Geometry. * @param {ol.Size} size Box pixel size. + * @param {olx.view.FitOptions=} opt_options Options. * @api */ -ol.View.prototype.fitExtent = function(extent, size) { - if (!ol.extent.isEmpty(extent)) { - this.setCenter(ol.extent.getCenter(extent)); - var resolution = this.getResolutionForExtent(extent, size); - var constrainedResolution = this.constrainResolution(resolution, 0, 0); - if (constrainedResolution < resolution) { - constrainedResolution = - this.constrainResolution(constrainedResolution, -1, 0); - } - this.setResolution(constrainedResolution); +ol.View.prototype.fit = function(geometry, size, opt_options) { + if (!(geometry instanceof ol.geom.SimpleGeometry)) { + goog.asserts.assert(goog.isArray(geometry), + 'invalid extent or geometry'); + goog.asserts.assert(!ol.extent.isEmpty(geometry), + 'cannot fit empty extent'); + geometry = ol.geom.Polygon.fromExtent(geometry); } -}; - -/** - * Fit the given geometry into the view based on the given map size and border. - * @param {ol.geom.SimpleGeometry} geometry Geometry. - * @param {ol.Size} size Box pixel size. - * @param {olx.view.FitGeometryOptions=} opt_options Options. - * @api - */ -ol.View.prototype.fitGeometry = function(geometry, size, opt_options) { var options = goog.isDef(opt_options) ? opt_options : {}; var padding = goog.isDef(options.padding) ? options.padding : [0, 0, 0, 0]; diff --git a/test/spec/ol/view.test.js b/test/spec/ol/view.test.js index c4f3eb02cd..b4ef6bd69b 100644 --- a/test/spec/ol/view.test.js +++ b/test/spec/ol/view.test.js @@ -364,15 +364,44 @@ describe('ol.View', function() { }); }); - describe('fitGeometry', function() { + describe('#calculateExtent', function() { + it('returns the expected extent', function() { + var view = new ol.View({ + resolutions: [512], + zoom: 0, + center: [0, 0] + }); + + var extent = view.calculateExtent([100, 200]); + expect(extent[0]).to.be(-25600); + expect(extent[1]).to.be(-51200); + expect(extent[2]).to.be(25600); + expect(extent[3]).to.be(51200); + }); + it('returns the expected extent with rotation', function() { + var view = new ol.View({ + resolutions: [512], + zoom: 0, + center: [0, 0], + rotation: Math.PI / 2 + }); + var extent = view.calculateExtent([100, 200]); + expect(extent[0]).to.roughlyEqual(-51200, 1e-9); + expect(extent[1]).to.roughlyEqual(-25600, 1e-9); + expect(extent[2]).to.roughlyEqual(51200, 1e-9); + expect(extent[3]).to.roughlyEqual(25600, 1e-9); + }); + }); + + describe('fit', function() { var view; beforeEach(function() { view = new ol.View({ resolutions: [200, 100, 50, 20, 10, 5, 2, 1] }); }); - it('fit correctly to the geometry', function() { - view.fitGeometry( + it('fits correctly to the geometry', function() { + view.fit( new ol.geom.LineString([[6000, 46000], [6000, 47100], [7000, 46000]]), [200, 200], { @@ -384,7 +413,7 @@ describe('ol.View', function() { expect(view.getCenter()[0]).to.be(5950); expect(view.getCenter()[1]).to.be(47100); - view.fitGeometry( + view.fit( new ol.geom.LineString([[6000, 46000], [6000, 47100], [7000, 46000]]), [200, 200], { @@ -395,7 +424,7 @@ describe('ol.View', function() { expect(view.getCenter()[0]).to.be(5500); expect(view.getCenter()[1]).to.be(47550); - view.fitGeometry( + view.fit( new ol.geom.LineString([[6000, 46000], [6000, 47100], [7000, 46000]]), [200, 200], { @@ -407,7 +436,7 @@ describe('ol.View', function() { expect(view.getCenter()[0]).to.be(6000); expect(view.getCenter()[1]).to.be(47050); - view.fitGeometry( + view.fit( new ol.geom.Point([6000, 46000]), [200, 200], { @@ -419,7 +448,7 @@ describe('ol.View', function() { expect(view.getCenter()[0]).to.be(5900); expect(view.getCenter()[1]).to.be(46100); - view.fitGeometry( + view.fit( new ol.geom.Point([6000, 46000]), [200, 200], { @@ -433,7 +462,7 @@ describe('ol.View', function() { expect(view.getCenter()[1]).to.be(46100); view.setRotation(Math.PI / 4); - view.fitGeometry( + view.fit( new ol.geom.LineString([[6000, 46000], [6000, 47100], [7000, 46000]]), [200, 200], { @@ -445,6 +474,22 @@ describe('ol.View', function() { expect(view.getCenter()[0]).to.roughlyEqual(5200, 1e-9); expect(view.getCenter()[1]).to.roughlyEqual(46300, 1e-9); }); + it('fit correctly to the extent', function() { + view.fit([1000, 1000, 2000, 2000], [200, 200]); + expect(view.getResolution()).to.be(5); + expect(view.getCenter()[0]).to.be(1500); + expect(view.getCenter()[1]).to.be(1500); + }); + it('throws on invalid geometry/extent value', function() { + expect(function() { + view.fit(true, [200, 200]); + }).to.throwException(); + }); + it('throws on empty extent', function() { + expect(function() { + view.fit(ol.extent.createEmpty(), [200, 200]); + }).to.throwException(); + }); }); describe('centerOn', function() { @@ -477,5 +522,6 @@ describe('ol.View', function() { }); goog.require('ol.View'); +goog.require('ol.extent'); goog.require('ol.geom.LineString'); goog.require('ol.geom.Point');