From 962260ac6d64308f3591b23c5ba1f1686ad8c0db Mon Sep 17 00:00:00 2001 From: Vladimir Agafonkin Date: Tue, 5 Aug 2014 15:34:18 +0300 Subject: [PATCH 1/9] basic world zoom restriction --- js/geo/transform.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/js/geo/transform.js b/js/geo/transform.js index b77db576322..07331c97c7e 100644 --- a/js/geo/transform.js +++ b/js/geo/transform.js @@ -13,6 +13,9 @@ function Transform(minZoom, maxZoom) { this._minZoom = minZoom || 0; this._maxZoom = maxZoom || 22; + this.minLat = -85; + this.maxLat = 85; + this.width = 0; this.height = 0; this.zoom = 0; @@ -61,6 +64,7 @@ Transform.prototype = { this.scale = this.zoomScale(zoom); this.tileZoom = Math.floor(zoom); this.zoomFraction = zoom - this.tileZoom; + this._constrain(); }, zoomScale: function(zoom) { return Math.pow(2, zoom); }, @@ -148,5 +152,14 @@ Transform.prototype = { row: tileCenter.row * kt - p2.y, zoom: this.tileZoom }; + }, + + _constrain: function() { + var minY = this.latY(this.maxLat), + maxY = this.latY(this.minLat), + dy = maxY - minY, + s = this.size; + + if (dy < s.y) this.zoom += this.scaleZoom(s.y / dy); } }; From cd9f887c610f77d115c4fb5ac9aa3821aec64730 Mon Sep 17 00:00:00 2001 From: Vladimir Agafonkin Date: Tue, 5 Aug 2014 15:49:09 +0300 Subject: [PATCH 2/9] basic panning restriction --- js/geo/transform.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/js/geo/transform.js b/js/geo/transform.js index 07331c97c7e..1121c1e2466 100644 --- a/js/geo/transform.js +++ b/js/geo/transform.js @@ -108,6 +108,7 @@ Transform.prototype = { panBy: function(offset) { var point = this.centerPoint._add(offset); this.center = this.pointLocation(point); + this._constrain(); }, zoomAroundTo: function(zoom, p) { @@ -155,11 +156,22 @@ Transform.prototype = { }, _constrain: function() { + if (!this.center) return; + var minY = this.latY(this.maxLat), maxY = this.latY(this.minLat), dy = maxY - minY, s = this.size; if (dy < s.y) this.zoom += this.scaleZoom(s.y / dy); + + var y = this.y, + h2 = s.y / 2, + y2; + + if (y - h2 < minY) y2 = minY + h2; + if (y + h2 > maxY) y2 = maxY - h2; + + if (y2) this.center = this.unproject(new Point(this.x, y2)); } }; From fbd4be6556eed03c90a818f5ce6e24b5e87904db Mon Sep 17 00:00:00 2001 From: Vladimir Agafonkin Date: Tue, 5 Aug 2014 21:39:24 +0300 Subject: [PATCH 3/9] add longitude constraints --- js/geo/transform.js | 63 +++++++++++++++++++++++++++++++++------------ 1 file changed, 46 insertions(+), 17 deletions(-) diff --git a/js/geo/transform.js b/js/geo/transform.js index 1121c1e2466..ac050483a1d 100644 --- a/js/geo/transform.js +++ b/js/geo/transform.js @@ -13,8 +13,7 @@ function Transform(minZoom, maxZoom) { this._minZoom = minZoom || 0; this._maxZoom = maxZoom || 22; - this.minLat = -85; - this.maxLat = 85; + this.latRange = [-85, 85]; this.width = 0; this.height = 0; @@ -158,20 +157,50 @@ Transform.prototype = { _constrain: function() { if (!this.center) return; - var minY = this.latY(this.maxLat), - maxY = this.latY(this.minLat), - dy = maxY - minY, - s = this.size; - - if (dy < s.y) this.zoom += this.scaleZoom(s.y / dy); - - var y = this.y, - h2 = s.y / 2, - y2; - - if (y - h2 < minY) y2 = minY + h2; - if (y + h2 > maxY) y2 = maxY - h2; - - if (y2) this.center = this.unproject(new Point(this.x, y2)); + var minY, maxY, minX, maxX, sy, sx, x2, y2, + size = this.size; + + if (this.latRange) { + minY = this.latY(this.latRange[1]); + maxY = this.latY(this.latRange[0]); + sy = maxY - minY < size.y ? size.y / (maxY - minY) : 0; + } + + if (this.lngRange) { + minX = this.lngX(this.lngRange[0]); + maxX = this.lngX(this.lngRange[1]); + sx = maxX - minX < size.x ? size.x / (maxX - minX) : 0; + } + + var s = Math.max(sx, sy); + + if (s) { + this.center = this.unproject(new Point( + sx ? (maxX + minX) / 2 : this.x, + sy ? (maxY + minY) / 2 : this.y)); + this.zoom += this.scaleZoom(s); + } + + if (this.latRange) { + var y = this.y, + h2 = size.y / 2; + + if (y - h2 < minY) y2 = minY + h2; + if (y + h2 > maxY) y2 = maxY - h2; + } + + if (this.lngRange) { + var x = this.x, + w2 = size.x / 2; + + if (x - w2 < minX) x2 = minX + w2; + if (x + w2 > maxX) x2 = maxX - w2; + } + + if (x2 !== undefined || y2 !== undefined) { + this.center = this.unproject(new Point( + x2 !== undefined ? x2 : this.x, + y2 !== undefined ? y2 : this.y)); + } } }; From 9008629114a7c37945c50527ab9f2706be1f5ffa Mon Sep 17 00:00:00 2001 From: Vladimir Agafonkin Date: Tue, 5 Aug 2014 21:59:28 +0300 Subject: [PATCH 4/9] fix scale constraints --- js/geo/transform.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/geo/transform.js b/js/geo/transform.js index ac050483a1d..e462b36ac13 100644 --- a/js/geo/transform.js +++ b/js/geo/transform.js @@ -172,7 +172,7 @@ Transform.prototype = { sx = maxX - minX < size.x ? size.x / (maxX - minX) : 0; } - var s = Math.max(sx, sy); + var s = Math.max(sx || 0, sy || 0); if (s) { this.center = this.unproject(new Point( From b50c91242c90533b7d8c362af447c7c0cefca92a Mon Sep 17 00:00:00 2001 From: Vladimir Agafonkin Date: Tue, 5 Aug 2014 22:37:31 +0300 Subject: [PATCH 5/9] minor constrain code cleanup --- js/geo/transform.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/js/geo/transform.js b/js/geo/transform.js index e462b36ac13..2d21afd24e6 100644 --- a/js/geo/transform.js +++ b/js/geo/transform.js @@ -157,19 +157,21 @@ Transform.prototype = { _constrain: function() { if (!this.center) return; - var minY, maxY, minX, maxX, sy, sx, x2, y2, + var minY, maxY, minX, maxX, dy, dx, sy, sx, x2, y2, size = this.size; if (this.latRange) { minY = this.latY(this.latRange[1]); maxY = this.latY(this.latRange[0]); - sy = maxY - minY < size.y ? size.y / (maxY - minY) : 0; + dy = maxY - minY; + sy = dy < size.y ? size.y / dy : 0; } if (this.lngRange) { minX = this.lngX(this.lngRange[0]); maxX = this.lngX(this.lngRange[1]); - sx = maxX - minX < size.x ? size.x / (maxX - minX) : 0; + dx = maxX - minX; + sx = dx < size.x ? size.x / dx : 0; } var s = Math.max(sx || 0, sy || 0); @@ -179,6 +181,7 @@ Transform.prototype = { sx ? (maxX + minX) / 2 : this.x, sy ? (maxY + minY) / 2 : this.y)); this.zoom += this.scaleZoom(s); + return; } if (this.latRange) { From 3ee6832177985f5fef6374a12dcbf3292781ef1a Mon Sep 17 00:00:00 2001 From: Vladimir Agafonkin Date: Tue, 5 Aug 2014 22:41:47 +0300 Subject: [PATCH 6/9] constrain on resize --- js/ui/map.js | 1 + 1 file changed, 1 insertion(+) diff --git a/js/ui/map.js b/js/ui/map.js index 598d510db33..dddc712a2b7 100644 --- a/js/ui/map.js +++ b/js/ui/map.js @@ -157,6 +157,7 @@ util.extend(Map.prototype, { this.transform.width = width; this.transform.height = height; + this.transform._constrain(); if (this.style && this.style.sprite) { this.style.sprite.resize(this.painter.gl); From b465691122d7a270f8b5aad0568a9a0878e721e7 Mon Sep 17 00:00:00 2001 From: Vladimir Agafonkin Date: Tue, 5 Aug 2014 22:49:45 +0300 Subject: [PATCH 7/9] add map maxBounds option --- js/ui/map.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/js/ui/map.js b/js/ui/map.js index dddc712a2b7..ce5bf98d61d 100644 --- a/js/ui/map.js +++ b/js/ui/map.js @@ -33,6 +33,12 @@ var Map = module.exports = function(options) { this.transform = new Transform(options.minZoom, options.maxZoom); this.hash = options.hash && new Hash(this); + if (options.maxBounds) { + var b = LatLngBounds.convert(options.maxBounds); + this.transform.latRange = [b.getSouth(), b.getNorth()]; + this.transform.lngRange = [b.getWest(), b.getEast()]; + } + this._onStyleChange = this._onStyleChange.bind(this); this._updateBuckets = this._updateBuckets.bind(this); this.render = this.render.bind(this); From 1ad93fa5018cc05659e4e24c31321416b031cb04 Mon Sep 17 00:00:00 2001 From: Vladimir Agafonkin Date: Tue, 5 Aug 2014 23:13:41 +0300 Subject: [PATCH 8/9] fix transform test --- test/js/geo/transform.test.js | 1 + 1 file changed, 1 insertion(+) diff --git a/test/js/geo/transform.test.js b/test/js/geo/transform.test.js index 78f05672185..fe46f329a6d 100644 --- a/test/js/geo/transform.test.js +++ b/test/js/geo/transform.test.js @@ -42,6 +42,7 @@ test('transform', function(t) { var transform = new Transform(); transform.width = 500; transform.height = 500; + transform.latRange = undefined; t.deepEqual(transform.center, { lat: 0, lng: 0 }); t.equal(transform.panBy(new Point(10, 10)), undefined); t.deepEqual(transform.center, { lat: -7.01366792756663, lng: 7.03125 }); From 53e8fd4c64b750ca91fdc3f99d565f4eaccfb4ac Mon Sep 17 00:00:00 2001 From: Vladimir Agafonkin Date: Wed, 6 Aug 2014 14:57:30 +0300 Subject: [PATCH 9/9] constrain cleanup and some comments --- js/geo/transform.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/js/geo/transform.js b/js/geo/transform.js index 2d21afd24e6..35b12c60086 100644 --- a/js/geo/transform.js +++ b/js/geo/transform.js @@ -157,23 +157,22 @@ Transform.prototype = { _constrain: function() { if (!this.center) return; - var minY, maxY, minX, maxX, dy, dx, sy, sx, x2, y2, + var minY, maxY, minX, maxX, sy, sx, x2, y2, size = this.size; if (this.latRange) { minY = this.latY(this.latRange[1]); maxY = this.latY(this.latRange[0]); - dy = maxY - minY; - sy = dy < size.y ? size.y / dy : 0; + sy = maxY - minY < size.y ? size.y / (maxY - minY) : 0; } if (this.lngRange) { minX = this.lngX(this.lngRange[0]); maxX = this.lngX(this.lngRange[1]); - dx = maxX - minX; - sx = dx < size.x ? size.x / dx : 0; + sx = maxX - minX < size.x ? size.x / (maxX - minX) : 0; } + // how much the map should scale to fit the screen into given latitude/longitude ranges var s = Math.max(sx || 0, sy || 0); if (s) { @@ -200,6 +199,7 @@ Transform.prototype = { if (x + w2 > maxX) x2 = maxX - w2; } + // pan the map if the screen goes off the range if (x2 !== undefined || y2 !== undefined) { this.center = this.unproject(new Point( x2 !== undefined ? x2 : this.x,