pin

Adjusting Zoom Level To Add Padding To Map Bounding Boxes – Bing Maps V7

Suppose you have a cluster of map pins, and you want the map to zoom and center on those pins such that they all fit on the user’s screen. This is normally accomplished by passing a list of pins into a helper method that spits out  a bounding box, you then set your map’s view to that bounding box.

The problem with this approach is that you will always end up with at least 2 pin from your cluster appearing on the absolute edge of your bounding box, which translates to being on the precise edge of the user’s screen. And depending on how your pins appear, it may be entirely invisible to your user, who may not realize they have to pan their view slightly to view the missing pin.

The solution is to add padding to the edges bounding box, so that we can be sure that all pins appear in the user’s view with some space to spare from the edges of the map. We can accomplish this by adding two fake pins (that won’t appear on the map) to our list of pins, positioned in such a way that they stretch the bounding box by a percentage of it’s original size.

Here is a diagram of what this approach looks like:

bingbounding

The solution can be broken down as such:

  1. While populating our list of pins to create our bounding box, keep track of the maximum and minimum values of both longitude and latitude for all pins. This will give us the boundaries of the original bounding box.
  2. Using the maximum and minimum values for both longitude and latitude, we can calculate the latitudinal width and longitudinal height of our original bounding box.
  3. We can apply an arbitrary percentage to the height and width of the bounding box and calculate the coordinates needed for our two fake pins. These fake pins will be outside of the original bounding box, and when added to our list of pins, will force the resulting bounding box to grow based on the percentage used in the calculations.
  4. Input the modified list of pins into the bounding box helper method, returning an expanded bounding box.

So what does this look like in code? (Bing Maps AJAX v7.0)

function focusOnPinCluster(cluster) {
	// array that stores our list of pin locations
	var locations = [];

	var maxLat = -90;
	var minLat = 90;
	var maxLon = -180;
	var minLon = 180;

	// populate the locations array with the passed in pins
	for (var i = 0; i < cluster.length; i++) {
		var pin = cluster[i];
		locations.push(new Microsoft.Maps.Location(pin.Latitude, pin.Longitude));

		// update max lat/long values
		if (pin.Latitude > maxLat) { maxLat = pin.Latitude; }
		if (pin.Latitude < minLat) { minLat = pin.Latitude; }
		if (pin.Longitude > maxLon) { maxLon = pin.Longitude; }
		if (pin.Longitude < minLon) { minLon = pin.Longitude; }
	}

	// add 2 locations that push the bounding box out by a % of its size
	var pctBuffer = 0.05;
	var latBuffer = (maxLat - minLat) * pctBuffer;
	var lonBuffer = (maxLon - minLon) * pctBuffer;

	// add the two fakes pins to our location array
	locations.push(new Microsoft.Maps.Location(minLat - latBuffer, maxLon + lonBuffer));
	locations.push(new Microsoft.Maps.Location(maxLat + latBuffer, minLon - lonBuffer));

	// create a bounding box based on our location array
	var bounds = Microsoft.Maps.LocationRect.fromLocations(locations);

	// set the map view to our bounding box
	_map.setView({ bounds: bounds });
}

The result will have our cluster of pins appear zoomed and centered in the map, with a healthy margin between the pins and the edge of the screen.