Question

I have a map which contains multiple markers with infowindows. The infowindows need to be open on page load. The map is being centered using setbounds to incorporate all of the markers, which works, but it also needs to include the infowindows within the bounds. Currently the infowindows are cropped in places.

JS:

function initialize() {
    var map = new google.maps.Map(document.getElementById('map-canvas'));
    var bounds = new google.maps.LatLngBounds();
    var myLatlng1 = new google.maps.LatLng(51.525209,-0.09402479999994284)
    var contentString1 = '<div class="map-content"><p>Test1<br/ >dsfasdf<br/ >dsfasdf<br/ >dsfasdf<br/ >dsfasdf<br/ >dsfasdf<br/ >dsfasdf</p></div>'
    var infowindow1 = new google.maps.InfoWindow({content: contentString1});
    var marker1 = new google.maps.Marker({position: myLatlng1,map: map,title: 'Test1'});

    google.maps.event.addListener(marker1, 'click', function() {infowindow1.open(map,marker1);});
    infowindow1.open(map,marker1);
    bounds.extend(myLatlng1);

    var myLatlng2 = new google.maps.LatLng(51.52106840183588,-0.10866641049801729)
    var contentString2 = '<div class="map-content"><p><br/ >dsfasdf<br/ >dsfasdf<br/ >dsfasdf<br/ >dsfasdf<br/ >dsfasdf</p></div>'
    var infowindow2 = new google.maps.InfoWindow({content: contentString2});
    var marker2 = new google.maps.Marker({position: myLatlng2,map: map,title: 'Test2'});
    google.maps.event.addListener(marker2, 'click', function() {infowindow2.open(map,marker2);});
    infowindow2.open(map,marker2);
    bounds.extend(myLatlng2)

    //  Fit these bounds to the map
    map.fitBounds(bounds);
}
google.maps.event.addDomListener(window, 'load', initialize);

CSS:

#map-canvas { width: 100%; height: 520px; }

You can see a fiddle here: http://jsfiddle.net/mKKVM/

Can anyone suggest how to get the infowindows inside the bounds?

Was it helpful?

Solution

Proof of concept jsfiddle

  1. Display the map normally
  2. Calculate the pixel distance from the marker anchor to the upper edge of the infowindow
  3. Calculate the pixel distance from the marker anchor to the left edge of the infowindow
  4. Calculate the pixel distance from the marker anchor to the right edge of the infowindow
  5. Extend the the original bounds with two points made from the right corner of the bounds plus half the width of the infowindow and the top of the bounds plus the height of the infowindow.
  6. Extend the the original bounds with two points made from the left corner of the bounds minus half the width of the infowindow and the top of the bounds plus the height of the infowindow.
  7. fit the map to the new bounds.

Probably can be refined to use 3 points top center, left center and right center, this is a first cut, proof of concept, can probably be cleaned up and refined.

function initialize() {
  var map = new google.maps.Map(document.getElementById('map-canvas'));
  var projection = null; 
  google.maps.event.addListener(map,'projection_changed', function() {
    projection = map.getProjection();
  }); 

  var bounds = new google.maps.LatLngBounds();
  if (!projection) 
    google.maps.event.addListener(map, 'idle', computeBounds);
  else 
    computeBounds();

  var myLatlng1 = new google.maps.LatLng(51.525209,-0.09402479999994284);
  bounds.extend(myLatlng1);
  var myLatlng2 = new google.maps.LatLng(51.52106840183588,-0.10866641049801729);
  bounds.extend(myLatlng2);
  //  Fit these bounds to the map
  map.fitBounds(bounds);

  function computeBounds() {    

    var contentString1 = '<div class="map-content"><p>Test1<br />dsfasdf<br />dsfasdf<br />dsfasdf<br />dsfasdf<br />dsfasdf<br />dsfasdf</p></div>'
    var infowindow1 = new google.maps.InfoWindow({content: contentString1});
    var marker1 = new google.maps.Marker({position: myLatlng1,map: map,title: 'Test1'});

    google.maps.event.addListener(marker1, 'click', function() {
      infowindow1.open(map,marker1);
    });
    infowindow1.open(map,marker1);
    google.maps.event.addListenerOnce(infowindow1,'domready',calcInfoWindowBounds); 

    var contentString2 = '<div class="map-content"><p><br />dsfasdf<br />dsfasdf<br />dsfasdf<br />dsfasdf<br />dsfasdf</p></div>'
    var infowindow2 = new google.maps.InfoWindow({content: contentString2});
    var marker2 = new google.maps.Marker({position: myLatlng2,map: map,title: 'Test2'});
    google.maps.event.addListener(marker2, 'click', function() {
      infowindow2.open(map,marker2);
    });
    infowindow2.open(map,marker2);

    google.maps.event.addListenerOnce(infowindow2,'domready',calcInfoWindowBounds); 

    function calcInfoWindowBounds(){
      domEls = document.getElementsByClassName('map-content');
      var markerSpace = 32+8;
      var maxTop = 0;
      var maxLeft = 0;
      var maxRight = 0;
      for (var i=0; i<domEls.length; i++) {
        var topOfWindow = domEls[i].offsetHeight + markerSpace;
        var leftOfWindow = domEls[i].offsetWidth/2;
        var rightOfWindow = domEls[i].offsetWidth/2;

        if (topOfWindow > maxTop) maxTop = topOfWindow;
        if (leftOfWindow > maxLeft) maxLeft = leftOfWindow;
        if (rightOfWindow > maxRight) maxRight = rightOfWindow;
      }

      var leftBounds = projection.fromLatLngToPoint(new google.maps.LatLng(bounds.getNorthEast().lat(),bounds.getSouththWest().lng()));
      var rightBounds = projection.fromLatLngToPoint(new google.maps.LatLng(bounds.getNorthEast()));
      var topBounds0 = rightBounds.y + maxTop;
      var rightBounds0 = rightBounds.x + maxRight;
      var leftBounds0 = leftBounds.x - maxLeft;
      bounds.extend(projection.fromPointToLatLng(leftBounds0,topBounds0));
      bounds.extend(projection.fromPointToLatLng(rightBounds0,topBounds0));
      map.fitBounds(bounds);
    }   

  }

}
google.maps.event.addDomListener(window, 'load', initialize);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top