I am using Google Maps API v3 to create an inline map on a website. In its container element, I also have an absolute positioned overlay which shows some detail information, visually hovering over the map. Determining on context this element may grow up to the size of the entire map element.
All this is working fine, however the Maps instance of course still considers the overlaid part of the map a valid usable part of the map. This means that, especially if the overlay is at maximum height, setCenter
doesn't focus on the visible center, and routes drawn with DirectionsRenderer
are partially underneath the overlay.
See this image:
Is there a way to limit the actual viewport to the blueish area, so that setCenter
centers on the arrow tip and setBounds
fits to the blue part?
Find the “Layers” menu in the bottom left corner of the screen. Hover your cursor over the box and wait until more options appear. Click “More” to open the Map Details menu. Under “Map Type,” you'll see a checked box next to “Labels.” Uncheck it to remove all labels.
Use map images to create extra information without embedding it into your original map. To see how an overlay image corresponds to the map image underneath it: Select the overlay in the viewer. Then, change the transparency so that it's fully opaque.
> You should be able to set streetViewControl:false inhttp://code.google.com/apis/maps/documentation/javascript/reference.h... > > streetview pegman on my map. > > pegman too.
I have managed to implement an acceptably functional workaround for the time being.
Some general notes which are good to know:
Map
object has a Projection
, which can convert between LatLng points to map points.Projection
uses for calculation are in 'world' coordinates, meaning they are pixels on the world map at zoom level 0.2 ^ zoom
.The samples below assume a 300px wide sidebar on the right - adapting to other borders should be easy.
Using this knowledge, it becomes trivial to write a custom function for off-center centering:
function setCenter(latlng)
{
var z = Math.pow(2, map.getZoom());
var pnt = map.getProjection().fromLatLngToPoint(latlng);
map.setCenter(map.getProjection().fromPointToLatLng(
new google.maps.Point(pnt.x + 150/z, pnt.y)));
}
The crucial bits here are the z
variable, and the pnt.x + 150/z
calculation in the final line. Because of the above assumptions, this moves the point to center on 150 pixels to the left for the current zoom level, and as such compensates for the missing 300 pixels on the right sidebar.
The bounds issue is far less trivial. The reason for this is that to offset the points correctly, you need to know the zoom level. For recentering this doesn't change, but for fitting to previously unknown bounds it nearly always will. Since Google Maps uses unknown margins itself internally when fitting to bounds, there is no reliable way to predict the required zoom level.
Thus a possible solution is to invoke a two-step rocket. First off, call fitBounds
with the entire map. This should make the bounds and zoom level at least nearly correct. Then right after that, do a second call to fitBounds
corrected for the sidebar.
The following sample implementation should be called with a LatLngBounds
object as parameter, or no parameters to default to the current bounds.
function setBounds(bnd, cb)
{
var prj = map.getProjection();
if(!bnd) bnd = map.getBounds();
var ne = prj.fromLatLngToPoint(bnd.getNorthEast()),
sw = prj.fromLatLngToPoint(bnd.getSouthWest());
if(cb) ne.x += (300 / Math.pow(2, map.getZoom()));
else google.maps.event.addListenerOnce(map,'bounds_changed',
function(){setBounds(bnd,1)});
map.fitBounds(new google.maps.LatLngBounds(
prj.fromPointToLatLng(sw), prj.fromPointToLatLng(ne)));
}
What we do here at first is get the actual points of the bounds, and since cb
isn't set we install a once-only event on bounds_changed
, which is then fired after the fitBounds
is completed. This means that the function is automatically called a second time, after the zoom has been corrected. The second invocation, with cb=1
, then offsets the box to correct for the 300 pixel wide sidebar.
In certain cases, this can lead to a slight off-animation, but in practice I've only seen this occur when really spamclicking on buttons causing a fit operation. It's running perfectly well otherwise.
Hope this helps someone :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With