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

cordova, google-maps-api-3, javascript

Solution

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

Problem

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.

Original source

Related problems