Google Maps API fitbounds moving map to left or right - javascript

I have an application where I save center latitude, longitude and the distance between the center and the North East corner of the map, in this way we could draw the map with the same bounds we saved.
The first issue I faced when I was drawing the map with the stored data was that using fitbounds() a margin is added to the bounds I pass, this added an extra zoom level, with it the map looks very different to the original version of the map. To fix it I recalculate the bounds with the solution #6 from : https://code.google.com/p/gmaps-api-issues/issues/detail?id=3117
I use map.fitbounds(new bounds) with the result of recalculating the bounds due to the margin added by the fitbounds method.
But now I noticed that when I draw a map with the values stored in database, the map is being moved to the right or left randomly, this is more notorius on low zoom levels. I hope you can give an idea why this is happening or how can I fix it. Thank you.

You can write your custom function to work around a margin. Please look at the implementation of myFitBounds() function.
code snippet:
var map;
function myFitBounds(myMap, bounds) {
myMap.fitBounds(bounds);
var overlayHelper = new google.maps.OverlayView();
overlayHelper.draw = function () {
if (!this.ready) {
var projection = this.getProjection(),
zoom = getExtraZoom(projection, bounds, myMap.getBounds());
if (zoom > 0) {
myMap.setZoom(myMap.getZoom() + zoom);
}
this.ready = true;
google.maps.event.trigger(this, 'ready');
}
};
overlayHelper.setMap(myMap);
}
// LatLngBounds b1, b2 -> zoom increment
function getExtraZoom(projection, expectedBounds, actualBounds) {
var expectedSize = getSizeInPixels(projection, expectedBounds),
actualSize = getSizeInPixels(projection, actualBounds);
if (Math.floor(expectedSize.x) == 0 || Math.floor(expectedSize.y) == 0) {
return 0;
}
var qx = actualSize.x / expectedSize.x;
var qy = actualSize.y / expectedSize.y;
var min = Math.min(qx, qy);
if (min < 1) {
return 0;
}
return Math.floor(Math.log(min) / Math.log(2) /* = log2(min) */);
}
// LatLngBounds bnds -> height and width as a Point
function getSizeInPixels(projection, bounds) {
var sw = projection.fromLatLngToContainerPixel(bounds.getSouthWest());
var ne = projection.fromLatLngToContainerPixel(bounds.getNorthEast());
return new google.maps.Point(Math.abs(sw.y - ne.y), Math.abs(sw.x - ne.x));
}
function initialize() {
var mapOptions = {
zoom: 8,
center: new google.maps.LatLng(-34.397, 150.644),
panControl: false,
zoomControl: false,
mapTypeControl: false,
scaleControl: false,
streetViewControl: false,
overviewMapControl: false
};
map = new google.maps.Map(document.getElementById('map-canvas'),mapOptions);
bounds = new google.maps.LatLngBounds();
var extendPoint1 = new google.maps.LatLng(35.491823,6.626860999999963);
var extendPoint2 = new google.maps.LatLng(47.09192,18.520579999999995);
new google.maps.Marker({position: extendPoint1,map: map});
new google.maps.Marker({position: extendPoint2,map: map});
bounds.extend(extendPoint1);
bounds.extend(extendPoint2);
myFitBounds(map,bounds);
//map.fitBounds(bounds);
}
html,
body,
#map-canvas {
height: 100%;
width: 100%;
margin: 0px;
padding: 0px
}
<div id="map-canvas"></div>
<script async defer src="https://maps.googleapis.com/maps/api/js?v=3&libraries=places&callback=initialize"></script>

Related

Google Maps API 3 - Show All Markers on Screen, but Keep Centerpoint

This is very similar to this question. I would like to ensure that all markers are shown at the current zoom level. However, I would also like to choose the center point beforehand (current location of user). If circles are markers, and the square is my intended centerpoint, in the images below, the linked solution would create the first (left, top) image. I would like the second (right, bottom) image.
You can create a LatLngBounds object and extend it with each of your markers coordinates. Then get your bounds object north east and south west coordinates and check whether theses coordinates are contained within the current map bounds. If not, zoom out and try again.
Most of the below code is to generate random markers within certain bounds. The real interesting parts are where I call bounds.extend(position) and the fitAllBounds function.
var map, bounds;
function initialize() {
var southWest = new google.maps.LatLng(40, -70);
var northEast = new google.maps.LatLng(35, -80);
var lngSpan = northEast.lng() - southWest.lng();
var latSpan = northEast.lat() - southWest.lat();
var center = new google.maps.LatLng(40, -70);
map = new google.maps.Map(document.getElementById("map-canvas"), {
zoom: 12,
center: center,
mapTypeId: google.maps.MapTypeId.ROADMAP
});
// Add center marker
new google.maps.Marker({
position: center,
label: 'C',
map: map
});
// Create the bounds object
bounds = new google.maps.LatLngBounds();
// Create random markers
for (var i = 0; i < 20; i++) {
// Calculate a random position
var position = new google.maps.LatLng(southWest.lat() + latSpan * Math.random(), southWest.lng() + lngSpan * Math.random());
var marker = new google.maps.Marker({
position: position,
map: map
});
google.maps.event.addListener(marker, 'click', (function(marker, i) {
return function() {
map.setZoom(5);
map.setCenter(marker.position);
}
})(marker, i));
// Extend the bounds with the last marker position
bounds.extend(position);
}
// Fit all bounds once, when the map is ready
google.maps.event.addListenerOnce(map, 'idle', function() {
fitAllBounds(bounds);
});
}
function fitAllBounds(b) {
// Get north east and south west markers bounds coordinates
var ne = b.getNorthEast();
var sw = b.getSouthWest();
// Get the current map bounds
var mapBounds = map.getBounds();
// Check if map bounds contains both north east and south west points
if (mapBounds.contains(ne) && mapBounds.contains(sw)) {
// Everything fits
return;
} else {
var mapZoom = map.getZoom();
if (mapZoom > 0) {
// Zoom out
map.setZoom(mapZoom - 1);
// Try again
fitAllBounds(b);
}
}
}
initialize();
#map-canvas {
height: 200px;
width: 200px;
}
<div id="map-canvas"></div>
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk"></script>
Here it is also on JSFiddle:
JSFiddle demo

In Google Map's JS API fromPointToLatLng doesn't seem accurate based on events

My goal is when they have a drawing tool like the rectangle tool, if they single click somewhere it centers the map where they clicked as to make it easier for them to draw their rectangle without needing to switch tools or drag to the window edge and have it scroll.
I cannot use Google Map's events because they disable them if you use their DrawingManager, so I'm forced to use jQuery or vanilla JS.
I have a map that is 100% wide and ~50% of the window height. Here's the basic code I've been trying everything I can think of on:
$('#myMapWapperElement').on('click', function (event) {
var position = settings.map.getProjection().fromPointToLatLng(
new google.maps.Point(
event.offsetX,
event.offsetY
)
);
map.setCenter(position);
});
This, however, makes the map jump all over when I click. It doesn't center where the marker clicked at all. I tried offsetX, pageX, and also relative by offsetX - "elementPositionX". Nothing seems to center correctly.
The fromPointToLatLng and fromLatLngToPoint methods of google.maps.Projection object translate between points in a 256x256 coordinate system and real world coordinates. You could utilize the following function to translate from pixel coordinates on a map projection to LatLng values:
var fromPixelToLatLng = function (map, x, y) {
var projection = map.getProjection();
var topRight = projection.fromLatLngToPoint(map.getBounds().getNorthEast());
var bottomLeft = projection.fromLatLngToPoint(map.getBounds().getSouthWest());
var scale = 1 << map.getZoom();
return projection.fromPointToLatLng(new google.maps.Point(x / scale + bottomLeft.x, y / scale + topRight.y));
};
Example
function initMap() {
var map = new google.maps.Map(document.getElementById('map'), {
center: { lat: -34.397, lng: 150.644 },
zoom: 8
});
var infowindow = new google.maps.InfoWindow({
content: ''
});
$("#map").on('click', function (event) {
var position = fromPixelToLatLng(map, event.offsetX, event.offsetY);
infowindow.setContent('Pixel(' + event.offsetX + ',' + event.offsetY + ') -> LatLng:' + position.toString());
infowindow.setPosition(position);
infowindow.open(map);
map.setCenter(position);
});
//var drawingManager = new google.maps.drawing.DrawingManager({
// drawingMode: google.maps.drawing.OverlayType.MARKER,
// drawingControl: true,
// drawingControlOptions: {
// position: google.maps.ControlPosition.TOP_CENTER,
// drawingModes: [
// google.maps.drawing.OverlayType.MARKER,
// google.maps.drawing.OverlayType.CIRCLE,
// google.maps.drawing.OverlayType.POLYGON,
// google.maps.drawing.OverlayType.POLYLINE,
// google.maps.drawing.OverlayType.RECTANGLE
// ]
// }
//});
//drawingManager.setMap(map);
}
var fromPixelToLatLng = function (map, x, y) {
var projection = map.getProjection();
var topRight = projection.fromLatLngToPoint(map.getBounds().getNorthEast());
var bottomLeft = projection.fromLatLngToPoint(map.getBounds().getSouthWest());
var scale = 1 << map.getZoom();
return projection.fromPointToLatLng(new google.maps.Point(x / scale + bottomLeft.x, y / scale + topRight.y));
};
html, body {
height: 100%;
margin: 0;
padding: 0;
}
#map {
height: 100%;
}
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<div id="map"></div>
<script src="https://maps.googleapis.com/maps/api/js?libraries=drawing&callback=initMap"
async defer></script>
You need to use the .fromContainerPixelToLatLng of MapCanvasProjection
That method is available on the OverlayView class.
proof of concept fiddle
code snippet:
var geocoder;
var map;
function initialize() {
map = new google.maps.Map(
document.getElementById("map_canvas"), {
center: new google.maps.LatLng(37.4419, -122.1419),
zoom: 13,
mapTypeId: google.maps.MapTypeId.ROADMAP
});
overlay = new google.maps.OverlayView();
overlay.draw = function() {
console.log("draw");
};
overlay.setMap(map);
google.maps.event.addListener(overlay, 'projection_changed', function() {
var projection = overlay.getProjection();
$('#map_canvas').on('click', function(event) {
var position = projection.fromContainerPixelToLatLng(
new google.maps.Point(
event.offsetX,
event.offsetY
)
);
map.setCenter(position);
});
})
}
google.maps.event.addDomListener(window, "load", initialize);
html,
body,
#map_canvas {
height: 100%;
width: 100%;
margin: 0px;
padding: 0px
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://maps.googleapis.com/maps/api/js"></script>
<div id="map_canvas"></div>

Google Maps with satellite base Map and imageMapType overlay increase zoom

I am displaying an ImageMapType as overlay over a satellite mapType base map.
The base map seems to be limiting the max zoom to 19 in my area, if I change to a Road mapType I get a a couple of more levels. I have high resolution imaginery which I am displaying in the overlay and I want to be able to zoom further. If I use the ImageMapType as base map I can zoom in all I need, but I would really like to display the satellite base map and then continue to zoom into the image even if there's no satellite imaginery available.
Is there any way of accomplishing this? The only thing I can think of is creating a custom base map.
Code is similar to this example https://developers.google.com/maps/documentation/javascript/examples/maptype-image-overlay
Thanks!
My code:
var mapMinZoom = 10;
var mapMaxZoom = 25;
var zoom = 20;
function initialize() {
map = new google.maps.Map(document.getElementById('map-canvas'), {
center: new google.maps.LatLng(-34.567426059726316, -60.34467143006623),
zoom: zoom,
mapTypeId: google.maps.MapTypeId.SATELLITE,
panControl: false,
streetViewControl: false,
maxZoom: mapMaxZoom
});
createImageLayer('imaginery', 'images')
}
function createImageLayer(key, folder) {
var mapBounds = new google.maps.LatLngBounds(new google.maps.LatLng(-34.55771388565057, -60.367219001054764), new google.maps.LatLng(-34.55817334541287, -60.3209562599659));
var imageMapTypeLayer = new google.maps.ImageMapType({
minZoom: mapMinZoom,
maxZoom: mapMaxZoom,
name: key,
getTileUrl: function(coord, zoom) {
if ((zoom < mapMinZoom) || (zoom > mapMaxZoom)) {
return "http://www.maptiler.org/img/none.png";
}
var ymax = 1 << zoom;
var y = ymax - coord.y -1;
var tileBounds = new google.maps.LatLngBounds(
map.getProjection().fromPointToLatLng( new google.maps.Point( (coord.x), (coord.y) ) ),
map.getProjection().fromPointToLatLng( new google.maps.Point( (coord.x), (coord.y)))
);
// write a real condition here, so long this is always valid
if (tileBounds.intersects(tileBounds)) {
return "/static/ui/"+ folder + "/"+zoom+"/"+coord.x+"/"+y+".png";
} else {
return "http://www.maptiler.org/img/none.png";
}
},
tileSize: new google.maps.Size(256, 256)
});
map.overlayMapTypes.push(imageMapTypeLayer)
}
EDIT 1:
Up to now I have managed to overcome this by listening to the zoom_changed event and changing the base map to my imageMapType when the zoom reaches the maximum and back to satellite when the user zooms out. I wonder if there's a cleaner solution to this issue.

Horizontal repeating Google Maps Marker on ImageMapType

<!DOCTYPE html>
<html>
<head>
<title>Image map types</title>
<style>
html, body, #map-canvas {
height: 100%;
margin: 0px;
padding: 0px
}
</style>
<script src="https://maps.googleapis.com/maps/api/js?v=3.exp"></script>
<script>
var moonTypeOptions = {
getTileUrl: function(coord, zoom) {
var bound = Math.pow(2, zoom);
return 'full-out' +
'/' + zoom + '/' + coord.x + '/' +
(bound - coord.y - 1) + '.png';
},
tileSize: new google.maps.Size(256, 256),
maxZoom: 6,
minZoom: 1,
radius: 1738000,
name: 'Moon'
};
var moonMapType = new google.maps.ImageMapType(moonTypeOptions);
function initialize() {
var myLatlng = new google.maps.LatLng(0, 0);
var mapOptions = {
center: myLatlng,
zoom: 1,
streetViewControl: false,
mapTypeControlOptions: {
mapTypeIds: ['moon']
}
};
var map = new google.maps.Map(document.getElementById('map-canvas'),
mapOptions);
map.mapTypes.set('moon', moonMapType);
map.setMapTypeId('moon');
var marker = new google.maps.Marker({
position: myLatlng,
map: map,
title: 'Hello World!'
});
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>
</head>
<body>
<div id="map-canvas"></div>
</body>
</html>
I have above code to render a custom large 16834 * 16834 image of 19 mb which is broken into tiles using gdal2tiles and gdal_translate. In short, I have all the corresponding tiles.
The above code is working perfectly fine rendering image and different zoom levels. However, when I add marker, it is displayed multiple times at lower zoom level. I would like the marker not repeat itself horizontally.
Is there any way to avoid horizontal repeating markers? Currently, I'm using Leaflet.js which doesn't repeat marker horizontally as Google Maps library.
I want to use Google maps because of its stability and popularity.
I'm using Ubuntu 14.04 as OS.
set the optimized-option of the markers to false
For those who has still this problem, have a look at my solution.
1- Set the maps zoom to (2) and add marker positions (lat,long) i.e
var minZoomLevel = 2;
map.setZoom(minZoomLevel);
var bounds = new google.maps.LatLngBounds();
for (var i = 0; i < result.length; i++){
var latlng = new google.maps.LatLng(result[i].Lat, result[i].Lng);
bounds.extend(latlng);
});
2- Attach a event listener on zoom changed i.e
google.maps.event.addListener(map, 'zoom_changed', function() {
if (map.getZoom() < minZoomLevel) map.setZoom(minZoomLevel);
});
3- Attach a center changed listener (This done the trick) i.e
google.maps.event.addListener(map, 'center_changed', function()
{
checkBounds(bounds);
}
function checkBounds(allowedBounds) {
if(allowedBounds.contains(map.getCenter())) {
return;
}
var mapCenter = map.getCenter();
var X = mapCenter.lng();
var Y = mapCenter.lat();
var AmaxX = allowedBounds.getNorthEast().lng();
var AmaxY = allowedBounds.getNorthEast().lat();
var AminX = allowedBounds.getSouthWest().lng();
var AminY = allowedBounds.getSouthWest().lat();
if (X < AminX) {X = AminX;}
if (X > AmaxX) {X = AmaxX;}
if (Y < AminY) {Y = AminY;}
if (Y > AmaxY) {Y = AmaxY;}
map.setCenter(new google.maps.LatLng(Y,X));
}
Every time you change the center, it will check your points and restrict map to certain area . Setting zoom will show only one world tile, and check bound will restrict the horizontal scrolling, thats how your markers will show only one time in map, set zoom according to your condition that fits in !!

Google Maps v3 - limit viewable area and zoom level

is it possible to limit Google map v3 to a certain area? I want to allow displaying only some area (e.g. a country) and disallow the user to slide elsewhere. Also I want to restrict the zoom level - e.g. only between levels 6 and 9. And I want to use all the base map types.
Is there any way to achieve this?
I had a partial success with limiting zoom level by using StyledMap, but I succeeded only with restricting ROADMAP, I wasn't able to limit zoom on other basic types this way.
Thanks for any help
Better way to restrict zoom level might be to use the minZoom/maxZoom options rather than reacting to events?
var opt = { minZoom: 6, maxZoom: 9 };
map.setOptions(opt);
Or the options can be specified during map initialization, e.g.:
var map = new google.maps.Map(document.getElementById('map-canvas'), opt);
See: Google Maps JavaScript API V3 Reference
You can listen to the dragend event, and if the map is dragged outside the allowed bounds, move it back inside. You can define your allowed bounds in a LatLngBounds object and then use the contains() method to check if the new lat/lng center is within the bounds.
You can also limit the zoom level very easily.
Consider the following example: Fiddle Demo
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
<title>Google Maps JavaScript API v3 Example: Limit Panning and Zoom</title>
<script type="text/javascript"
src="http://maps.google.com/maps/api/js?sensor=false"></script>
</head>
<body>
<div id="map" style="width: 400px; height: 300px;"></div>
<script type="text/javascript">
// This is the minimum zoom level that we'll allow
var minZoomLevel = 5;
var map = new google.maps.Map(document.getElementById('map'), {
zoom: minZoomLevel,
center: new google.maps.LatLng(38.50, -90.50),
mapTypeId: google.maps.MapTypeId.ROADMAP
});
// Bounds for North America
var strictBounds = new google.maps.LatLngBounds(
new google.maps.LatLng(28.70, -127.50),
new google.maps.LatLng(48.85, -55.90)
);
// Listen for the dragend event
google.maps.event.addListener(map, 'dragend', function() {
if (strictBounds.contains(map.getCenter())) return;
// We're out of bounds - Move the map back within the bounds
var c = map.getCenter(),
x = c.lng(),
y = c.lat(),
maxX = strictBounds.getNorthEast().lng(),
maxY = strictBounds.getNorthEast().lat(),
minX = strictBounds.getSouthWest().lng(),
minY = strictBounds.getSouthWest().lat();
if (x < minX) x = minX;
if (x > maxX) x = maxX;
if (y < minY) y = minY;
if (y > maxY) y = maxY;
map.setCenter(new google.maps.LatLng(y, x));
});
// Limit the zoom level
google.maps.event.addListener(map, 'zoom_changed', function() {
if (map.getZoom() < minZoomLevel) map.setZoom(minZoomLevel);
});
</script>
</body>
</html>
Screenshot from the above example. The user will not be able to drag further south or far east in this case:
Good news. Starting from the version 3.35 of Maps JavaScript API, that was launched on February 14, 2019, you can use new restriction option in order to limit the viewport of the map.
According to the documentation
MapRestriction interface
A restriction that can be applied to the Map. The map's viewport will not exceed these restrictions.
source: https://developers.google.com/maps/documentation/javascript/reference/map#MapRestriction
So, now you just add restriction option during a map initialization and that it. Have a look at the following example that limits viewport to Switzerland
var map;
function initMap() {
map = new google.maps.Map(document.getElementById('map'), {
center: {lat: 46.818188, lng: 8.227512},
minZoom: 7,
maxZoom: 14,
zoom: 7,
restriction: {
latLngBounds: {
east: 10.49234,
north: 47.808455,
south: 45.81792,
west: 5.95608
},
strictBounds: true
},
});
}
#map {
height: 100%;
}
html, body {
height: 100%;
margin: 0;
padding: 0;
}
<div id="map"></div>
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyDztlrk_3CnzGHo7CFvLFqE_2bUKEq1JEU&callback=initMap" async defer></script>
I hope this helps!
To limit the zoom on v.3+.
in your map setting add default zoom level and minZoom or maxZoom (or both if required)
zoom levels are 0 to 19.
You must declare deafult zoom level if limitation is required. all are case sensitive!
function initialize() {
var mapOptions = {
maxZoom:17,
minZoom:15,
zoom:15,
....
Much better way to limit the range... used the contains logic from above poster.
var dragStartCenter;
google.maps.event.addListener(map, 'dragstart', function(){
dragStartCenter = map.getCenter();
});
google.maps.event.addListener(this.googleMap, 'dragend', function(){
if (mapBounds.contains(map.getCenter())) return;
map.setCenter(this.dragStart);
});
This can be used to re-center the map to a specific location. Which is what I needed.
var MapBounds = new google.maps.LatLngBounds(
new google.maps.LatLng(35.676263, 13.949096),
new google.maps.LatLng(36.204391, 14.89038));
google.maps.event.addListener(GoogleMap, 'dragend', function ()
{
if (MapBounds.contains(GoogleMap.getCenter()))
{
return;
}
else
{
GoogleMap.setCenter(new google.maps.LatLng(35.920242, 14.428825));
}
});
myOptions = {
center: myLatlng,
minZoom: 6,
maxZoom: 9,
styles: customStyles,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
Here's my variant to solve the problem of viewable area's limitation.
google.maps.event.addListener(this.map, 'idle', function() {
var minLat = strictBounds.getSouthWest().lat();
var minLon = strictBounds.getSouthWest().lng();
var maxLat = strictBounds.getNorthEast().lat();
var maxLon = strictBounds.getNorthEast().lng();
var cBounds = self.map.getBounds();
var cMinLat = cBounds.getSouthWest().lat();
var cMinLon = cBounds.getSouthWest().lng();
var cMaxLat = cBounds.getNorthEast().lat();
var cMaxLon = cBounds.getNorthEast().lng();
var centerLat = self.map.getCenter().lat();
var centerLon = self.map.getCenter().lng();
if((cMaxLat - cMinLat > maxLat - minLat) || (cMaxLon - cMinLon > maxLon - minLon))
{ //We can't position the canvas to strict borders with a current zoom level
self.map.setZoomLevel(self.map.getZoomLevel()+1);
return;
}
if(cMinLat < minLat)
var newCenterLat = minLat + ((cMaxLat-cMinLat) / 2);
else if(cMaxLat > maxLat)
var newCenterLat = maxLat - ((cMaxLat-cMinLat) / 2);
else
var newCenterLat = centerLat;
if(cMinLon < minLon)
var newCenterLon = minLon + ((cMaxLon-cMinLon) / 2);
else if(cMaxLon > maxLon)
var newCenterLon = maxLon - ((cMaxLon-cMinLon) / 2);
else
var newCenterLon = centerLon;
if(newCenterLat != centerLat || newCenterLon != centerLon)
self.map.setCenter(new google.maps.LatLng(newCenterLat, newCenterLon));
});
strictBounds is an object of new google.maps.LatLngBounds() type. self.gmap stores a Google Map object (new google.maps.Map()).
It really works but don't only forget to take into account the haemorrhoids with crossing 0th meridians and parallels if your bounds cover them.
For some reason
if (strictBounds.contains(map.getCenter())) return;
didnt work for me (maybe a southern hemisphere issue). I had to change it to:
function checkBounds() {
var c = map.getCenter(),
x = c.lng(),
y = c.lat(),
maxX = strictBounds.getNorthEast().lng(),
maxY = strictBounds.getNorthEast().lat(),
minX = strictBounds.getSouthWest().lng(),
minY = strictBounds.getSouthWest().lat();
if(x < minX || x > maxX || y < minY || y > maxY) {
if (x < minX) x = minX;
if (x > maxX) x = maxX;
if (y < minY) y = minY;
if (y > maxY) y = maxY;
map.setCenter(new google.maps.LatLng(y, x));
}
}
Hope it will help someone.
One solution is like, If you know the specific lat/lng.
google.maps.event.addListener(map, 'idle', function() {
map.setCenter(new google.maps.LatLng(latitude, longitude));
map.setZoom(8);
});
If don't have specific lat/lng
google.maps.event.addListener(map, 'idle', function() {
map.setCenter(map.getCenter());
map.setZoom(8);
});
or
google.maps.event.addListener(map, 'idle', function() {
var bounds = new google.maps.LatLngBounds();
map.setCenter(bounds.getCenter());
map.setZoom(8);
});
As of middle 2016, there is no official way to restrict viewable area. Most of ad-hoc solutions to restrict the bounds have a flaw though, because they don't restrict the bounds exactly to fit the map view, they only restrict it if the center of the map is out of the specified bounds. If you want to restrict the bounds to overlaying image like me, this can result in a behavior like illustrated below, where the underlaying map is visible under our image overlay:
To tackle this issue, I have created a library, which successfully restrict the bounds so you cannot pan out of the overlay.
However, as other existing solutions, it has a "vibrating" issue. When the user pans the map aggressively enough, after they release the left mouse button, the map still continues panning by itself, gradually slowing. I always return the map back to the bounds, but that results in kind of vibrating. This panning effect cannot be stopped with any means provided by the Js API at the moment. It seems that until google adds support for something like map.stopPanningAnimation() we won't be able to create a smooth experience.
Example using the mentioned library, the smoothest strict bounds experience I was able to get:
function initialise(){
var myOptions = {
zoom: 5,
center: new google.maps.LatLng(0,0),
mapTypeId: google.maps.MapTypeId.ROADMAP,
};
var map = new google.maps.Map(document.getElementById('map'), myOptions);
addStrictBoundsImage(map);
}
function addStrictBoundsImage(map){
var bounds = new google.maps.LatLngBounds(
new google.maps.LatLng(62.281819, -150.287132),
new google.maps.LatLng(62.400471, -150.005608));
var image_src = 'https://developers.google.com/maps/documentation/' +
'javascript/examples/full/images/talkeetna.png';
var strict_bounds_image = new StrictBoundsImage(bounds, image_src, map);
}
<script type="text/javascript" src="http://www.google.com/jsapi"></script>
<script type="text/javascript">
google.load("maps", "3",{other_params:"sensor=false"});
</script>
<body style="margin:0px; padding:0px;" onload="initialise()">
<div id="map" style="height:400px; width:500px;"></div>
<script type="text/javascript"src="https://raw.githubusercontent.com/matej-pavla/StrictBoundsImage/master/StrictBoundsImage.js"></script>
</body>
The library is also able to calculate the minimum zoom restriction automatically. It then restricts the zoom level using minZoom map's attribute.
Hopefully this helps someone who wants a solution which fully respect the given boundaries and doesn't want to allow panning out of them.
This may be helpful.
var myOptions = {
center: new google.maps.LatLng($lat,$lang),
zoom: 7,
disableDefaultUI: true,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
The Zoom level can be customizable according to the requirement.

Categories

Resources