I am using Mapbox GL JS and created a dynamic store locator based on their store locator demo. I am using fitBounds to include all store markers on the initial display of the map.
The problem is, it zooms in too close and the map needs a bit of padding. So, I'm trying to back out the zoom one level. The problem is, when I get the zoom level and back out one, the map is recentered to the original center of the map.
I have included code below where I try to reset the center to the fitBounds center but it's not working. Any idea what I'm doing wrong?
var bounds = new mapboxgl.LngLatBounds();
$(markers).each(function() {
var features = $(this);
bounds.extend(features[0].geometry.coordinates);
});
map.fitBounds(bounds);
var mapLat = map.getBounds().getCenter().lat;
var mapLong = map.getBounds().getCenter().long;
map.setCenter = (mapLat, mapLong);
var mapZoom = map.getZoom();
newZoom = mapZoom - 1;
map.setZoom(newZoom);
If all you want to achieve is to add padding to the bounds, mapbox-gl provides an option for this in fitBounds:
map.fitBounds(bounds, {padding: 100}) // adds 100px padding to the bounds
Here is the documentation: https://www.mapbox.com/mapbox-gl-js/api#map#fitbounds
Related
I'm using Here Maps JS SDK. I'd like to change marker's minimum zoom level after creating a marker. My use case is about toggling clustering, where min zoom level must be set to Inf when clustering is disabled.
Thanks.
At this moment isn't possible change minimum zoom level after creating a marker.
As workaround you can move the necessary markers to your own ObjectLayer and then use method setMin see please example:
var parisMarker = new H.map.Marker({lat:48.8567, lng:2.3508});
map.addObject(parisMarker); //added to default ObjectLayer
myProvider = new H.map.provider.LocalObjectProvider();
var myLayer = new H.map.layer.ObjectLayer(myProvider);
map.addLayer(myLayer);
myProvider.getRootGroup().addObjects([
parisMarker //moved to custom ObjectLayer - myLayer
]);
myLayer.setMin(8); //set minimum zoom level for all objects in the layer
See full example set min zoom level for a layer
I want to adjust map zoom at max where all markers can accommodate in it, I am able to add new markers and adjust zooming level with following code,
bounds.extend(markerPosition);
googleMap.fitBounds(bounds);
but I want this work in reverse too, like if I remove marker from map zooming level should be adjusted automatically.
Can we do it using Google "Bounds" API ?
Please help....
For overcoming this issues what I have done is, simply written a resetMapBounds() function as follows and called it everytime marker is added,edited or deleted and also adjusted zoom level as I required in it.
function resetMapBounds(){
var bounds = new google.maps.LatLngBounds();
for(var i=0;i<markers.length;i++){
bounds.extend(markers[i].position);
}
map.fitBounds(bounds);
if(map.getZoom()>18){
map.setZoom(18);
}
}
Code:
var map = L.map('map');
L.tileLayer('//{s}.tile.cloudmade.com/41339be4c5064686b781a5a00678de62/998/256/{z}/{x}/{y}.png',{minZoom:8, maxZoom:15}).addTo(map);
marker1 = L.marker([37.4185539, -122.0829068]).addTo(map);
marker1.bindPopup("Google Campus");
marker2 = L.marker([37.792359, -122.404686]).addTo(map);
marker2.bindPopup("Financial District");
var group = new L.featureGroup([marker1, marker2]);
map.fitBounds(group.getBounds());
The above code will center the map on the center of the markers, but does not set a zoom level so that the markers and only the markers are visible.
If I leave out the 'minZoom' attribute of the map object when adding the initial layer, the entire globe is visible. My desire is to have the map set a zoom and boundaries so that the markers are visible, and zoomed in. Any clues on how to accomplish this?
I thought that the fitBounds method would set a Zoom level, but for some reason in my situation it does not do so.
Your code is setting the map to a zoom level where both of the markers are visible at the highest possible zoom level. Because of the distance between the two markers and the way web mapping works, this is best fit using raster map tiles. Higher zoom levels will be zoomed in so much that you won't be able to see both markers.
As you can see at:
http://rolls.mit.edu/
I am doing the following:
create a map
map = new google.maps.Map(mapContainer, options);
add overlay
overlay = new google.maps.OverlayView();
overlay.draw = function() {};
overlay.setMap(map);
add canvas to overlay
overlay.getPanes().overlayLayer.appendChild(canvas);
Everything works well except when I zoom, the canvas remains the same size. Is it possible to zoom the canvas when you zoom in/out? Any pointers to examples?
You need to listen to the google.maps.Map zoom_changed event, get the new zoom level from the map (with map.getZoom()), then resize or modify your canvas element appropriately.
If you just want to draw a line, look at the google.maps.Polyline overlay, that has the zoom functionality built in.
You pretty much have to render a new canvas for whatever google zoom levels you want to support. The way I have addressed this is by setting a listener on the "idle" event for the map. This will fire once the map goes idle after a zoom or pan. Then you can determine if the zoom level has changes and act accordingly.
var map = new google.maps.Map(mapContainer, options);
var zoomLevel = 6; //some defaut
var handleBoundsChanged = function(){
var oldZoom = zoomLevel;
var zoomLevel = map.getZoom();
if( zoomLevel != oldZoom){
rebuildOverlayForZoom(zoomLevel)
}
}
google.maps.event.addListener (map, 'idle', handleBoundsChanged);
I am trying to get my custom markers to show up on my map after i have used the fitBounds() method to fit the boundaries of the map to the markers themselves.
I have done this by looping over the markers array and then extending the boundaries of the map to incorporate the marker co-ordinates.
This works fine with the stock google maps markers. However, my client wants to use quite large (36px by 57px) marker images for their site. How do i compensate for this when fitting the boundaries of the map?
At the moment when using the custom marker images they do not all fit inside the boundaries set.
Since you already have calculated the bounds, you may just need to extend the bounds to add enough buffer area to include the large images. The formula you can use to calculate or extend a bounds this way is called a convex hull; the Computational Geometry Algorithms Library has a section on 2D Convex Hull Algorithms or there is a JavaScript Quickhull Article that also includes a nifty online example near the bottom of the page. Hope this is helpful -
The cheap answer is to always zoom out one level after fitBounds(). But we can do a bit better.
I like writing hacks. Here I am making the assumption that the size of your marker will never be larger than 36x57. I tested a while back to find that fitBounds() leaves a margin of around 42 px between the edge and the closest marker (maybe not on mobiles), and I'm also assuming you are not repositioning the marker, that is, it will always be displayed above the given coordinate position. If icons run off to the other sides, adjustments are needed.
My hack takes advantage of a function that measures the pixel position of a LatLng (using the container version, I read here that the div version is not reliable with bounds changes).
Since we know the height of the icon, and where the topmost marker is, we can pan the map south a bit if it's determined to be offscreen. In case there's not enough margin below, the only option is to zoom out. My only concern is it will be jerky because it calls for two events: fitBounds and the custom panning/zooming. The only answer then would be to rewrite a custom fitBounds. When I tested manually the events ran smoothly.
http://jsfiddle.net/sZJjY/
Click to add cat icons, right-click to trigger the resize/panning.
Example: place 3-4 kitties, right-click, then purposely place another that goes off the top, right-click again.
function fitIcons() {
var left = 180.0;
var right = -180.0;
var top = -90.0;
var bottom = 90.0;
for (var i = 0; i < markers.length; i++) {
curlat = markers[i].getPosition().lat();
curlng = markers[i].getPosition().lng();
if(curlat > top) { top = curlat; }
if(curlat < bottom) { bottom = curlat; }
if(curlng > right) { right = curlng; }
if(curlng < left) { left = curlng; }
}
var overlay = new google.maps.OverlayView();
overlay.draw = function() {};
overlay.setMap(map);
map.fitBounds(new google.maps.LatLngBounds(
new google.maps.LatLng(bottom, left),
new google.maps.LatLng(top, right)));
topPixels = overlay.getProjection().fromLatLngToContainerPixel(
new google.maps.LatLng(top, right));
bottomPixels = overlay.getProjection().fromLatLngToContainerPixel(
new google.maps.LatLng(bottom, left));
topGap = topPixels.y;
bottomGap = $("#map_canvas").height() - bottomPixels.y;
if(topGap < iconHeight) {
if(bottomGap > iconHeight) {
map.panBy(0, topGap);
}
else {
map.setZoom(map.getZoom() - 1);
}
}
}