From 68472d888baeb06d25b92320bcb137caec1da7a8 Mon Sep 17 00:00:00 2001 From: Tim Schaub Date: Thu, 13 Sep 2007 15:27:35 +0000 Subject: [PATCH] Give the map a restrictedExtent property. Setting this property to some bounds causes map navigation to be limited to those bounds. Depending on the resolution settings, the viewport may still display area outside the restricted extent - though it will be centered on the restricted extent in that case. Using a combination of restrictedExtent and maxResolution, you can limit map navigation to the extent of your data (or any arbitrary extent). See the restricted-extent.html example (closes #340). git-svn-id: http://svn.openlayers.org/trunk/openlayers@4261 dc9f47b5-9b13-0410-9fdd-eb0c1a62fdaf --- examples/restricted-extent.html | 70 +++++++++++++++++++++++ lib/OpenLayers/Map.js | 50 ++++++++++++++++- tests/test_Map.html | 98 ++++++++++++++++++++++++++++++++- 3 files changed, 216 insertions(+), 2 deletions(-) create mode 100644 examples/restricted-extent.html diff --git a/examples/restricted-extent.html b/examples/restricted-extent.html new file mode 100644 index 0000000000..2f8dc0d6ef --- /dev/null +++ b/examples/restricted-extent.html @@ -0,0 +1,70 @@ + + + + + + + + +

OpenLayers Restricted Extent Example

+
+

+ Map navigation is limited by a combination of map and layer properties. + The base layer resolutions array controls the resolutions (or zoom + levels) available. The resolutions can be limited by setting a + maxResolution property or by explicitly specifying a resolutions + array. +

+

+ Navigation limited by the maxExtent property. A map cannot be panned + so that the center of the viewport is outside of the bounds specified + in maxExtent. If you wish to further restrict panning, use the + restrictedExtent property. With restrictedExtent set, the map cannot + be panned beyond the given bounds. If the maxResolution allows the + map to be zoomed to a resolution that displays an area bigger than + the restrictedExtent, the viewport will remain centered on the + restrictedExtent. +

+

+ + + + + diff --git a/lib/OpenLayers/Map.js b/lib/OpenLayers/Map.js index 996b6c630e..29b2965111 100644 --- a/lib/OpenLayers/Map.js +++ b/lib/OpenLayers/Map.js @@ -206,6 +206,17 @@ OpenLayers.Map = OpenLayers.Class({ */ minExtent: null, + /** + * APIProperty: restrictedExtent + * {} Limit map navigation to this extent where possible. + * If a non-null restrictedExtent is set, panning will be restricted + * to the given bounds. In addition, zooming to a resolution that + * displays more than the restricted extent will center the map + * on the restricted extent. If you wish to limit the zoom level + * or resolution, use maxResolution. + */ + restrictedExtent: null, + /** * APIProperty: numZoomLevels * {Integer} Number of zoom levels for the map. Defaults to 16. Set a @@ -1036,10 +1047,47 @@ OpenLayers.Map = OpenLayers.Class({ * TBD: reconsider forceZoomChange in 3.0 */ setCenter: function (lonlat, zoom, dragging, forceZoomChange) { - + if (!this.center && !this.isValidLonLat(lonlat)) { lonlat = this.maxExtent.getCenterLonLat(); } + + if(this.restrictedExtent != null) { + // In 3.0, decide if we want to change interpretation of maxExtent. + if(lonlat == null) { + lonlat = this.getCenter(); + } + if(zoom == null) { + zoom = this.getZoom(); + } + var resolution = null; + if(this.baseLayer != null) { + resolution = this.baseLayer.resolutions[zoom]; + } + var extent = this.calculateBounds(lonlat, resolution); + if(!this.restrictedExtent.containsBounds(extent)) { + var maxCenter = this.restrictedExtent.getCenterLonLat(); + if(extent.getWidth() > this.restrictedExtent.getWidth()) { + lonlat = new OpenLayers.LonLat(maxCenter.lon, lonlat.lat); + } else if(extent.left < this.restrictedExtent.left) { + lonlat = lonlat.add(this.restrictedExtent.left - + extent.left, 0); + } else if(extent.right > this.restrictedExtent.right) { + lonlat = lonlat.add(this.restrictedExtent.right - + extent.right, 0); + } + if(extent.getHeight() > this.restrictedExtent.getHeight()) { + lonlat = new OpenLayers.LonLat(lonlat.lon, maxCenter.lat); + } else if(extent.bottom < this.restrictedExtent.bottom) { + lonlat = lonlat.add(0, this.restrictedExtent.bottom - + extent.bottom); + } + else if(extent.top > this.restrictedExtent.top) { + lonlat = lonlat.add(0, this.restrictedExtent.top - + extent.top); + } + } + } var zoomChanged = forceZoomChange || ( (this.isValidZoomLevel(zoom)) && diff --git a/tests/test_Map.html b/tests/test_Map.html index 9e1d6c05c6..13370edc87 100644 --- a/tests/test_Map.html +++ b/tests/test_Map.html @@ -472,6 +472,102 @@ t.ok( newNumControls == oldNumControls, "removing bad controlid doesnt crash or decrease control count") } + function test_Map_restrictedExtent(t) { + t.plan(24); + var extent = new OpenLayers.Bounds(-180, -90, 180, 90); + var options = { + maxResolution: "auto" + }; + var map = new OpenLayers.Map("map", options); + var layer = new OpenLayers.Layer.WMS( + "test", + "http://octo.metacarta.com/cgi-bin/mapserv?", + {map: "/mapdata/vmap_wms.map", layers: "basic"} + ); + map.addLayer(layer); + map.zoomToMaxExtent(); + var nw = new OpenLayers.LonLat(extent.left, extent.top); + var ne = new OpenLayers.LonLat(extent.right, extent.top); + var sw = new OpenLayers.LonLat(extent.left, extent.bottom); + var se = new OpenLayers.LonLat(extent.right, extent.bottom); + + // try panning to northwest corner + map.setOptions({restrictedExtent: extent}); + map.setCenter(nw, 0); + t.eq(map.getExtent().getCenterLonLat().toString(), + extent.getCenterLonLat().toString(), + "map extent properly restricted to northwest at zoom 0"); + t.eq(map.zoom, 0, "zoom not restricted for nw, 0"); + map.setCenter(nw, 5); + t.eq(map.getExtent().top, extent.top, + "map extent top properly restricted to northwest at zoom 5"); + t.eq(map.getExtent().left, extent.left, + "map extent left properly restricted to northwest at zoom 5"); + t.eq(map.zoom, 5, "zoom not restricted for nw, 5"); + map.setOptions({restrictedExtent: null}); + map.setCenter(nw, 0); + t.eq(map.getExtent().getCenterLonLat().toString(), + nw.toString(), + "map extent not restricted with null restrictedExtent for nw"); + + // try panning to northeast corner + map.setOptions({restrictedExtent: extent}); + map.setCenter(ne, 0); + t.eq(map.getExtent().getCenterLonLat().toString(), + extent.getCenterLonLat().toString(), + "map extent properly restricted to northeast at zoom 0"); + t.eq(map.zoom, 0, "zoom not restricted for ne, 0"); + map.setCenter(ne, 5); + t.eq(map.getExtent().top, extent.top, + "map extent top properly restricted to northeast at zoom 5"); + t.eq(map.getExtent().right, extent.right, + "map extent right properly restricted to northeast at zoom 5"); + t.eq(map.zoom, 5, "zoom not restricted for ne, 5"); + map.setOptions({restrictedExtent: null}); + map.setCenter(ne, 0); + t.eq(map.getExtent().getCenterLonLat().toString(), + ne.toString(), + "map extent not restricted with null restrictedExtent for ne"); + + // try panning to southwest corner + map.setOptions({restrictedExtent: extent}); + map.setCenter(sw, 0); + t.eq(map.getExtent().getCenterLonLat().toString(), + extent.getCenterLonLat().toString(), + "map extent properly restricted to southwest at zoom 0"); + t.eq(map.zoom, 0, "zoom not restricted for sw, 0"); + map.setCenter(sw, 5); + t.eq(map.getExtent().bottom, extent.bottom, + "map extent bottom properly restricted to southwest at zoom 5"); + t.eq(map.getExtent().left, extent.left, + "map extent left properly restricted to southwest at zoom 5"); + t.eq(map.zoom, 5, "zoom not restricted for sw, 5"); + map.setOptions({restrictedExtent: null}); + map.setCenter(sw, 0); + t.eq(map.getExtent().getCenterLonLat().toString(), + sw.toString(), + "map extent not restricted with null restrictedExtent for sw"); + + // try panning to southeast corner + map.setOptions({restrictedExtent: extent}); + map.setCenter(se, 0); + t.eq(map.getExtent().getCenterLonLat().toString(), + extent.getCenterLonLat().toString(), + "map extent properly restricted to southeast at zoom 0"); + t.eq(map.zoom, 0, "zoom not restricted for se, 0"); + map.setCenter(se, 5); + t.eq(map.getExtent().bottom, extent.bottom, + "map extent bottom properly restricted to southeast at zoom 5"); + t.eq(map.getExtent().right, extent.right, + "map extent right properly restricted to southeast at zoom 5"); + t.eq(map.zoom, 5, "zoom not restricted for se, 5"); + map.setOptions({restrictedExtent: null}); + map.setCenter(se, 0); + t.eq(map.getExtent().getCenterLonLat().toString(), + se.toString(), + "map extent not restricted with null restrictedExtent for se"); + } + function test_99_Map_destroy (t) { t.plan( 3 ); map = new OpenLayers.Map('map'); @@ -484,6 +580,6 @@ -

+