Centering a Google Map For Printing

While working on a recent project I came upon the situation where I needed a printer friendly version of a Google map.

The issue is the main browser view had the map sized to 100% and the print view was limited to 600px. The print height was also a bit shorter.

map-main-view.jpg

Main Browser View (Shrunk down from 1340 x 490 px)

When the client prints the page, the visible map in the browser gets cropped to the print size from the top left, which had a tendency to cut off all the markers in the center of the map.

map-main-view.jpg

Print view when printing from the main browser map

The behavior I wanted to see upon printing was the map cropped from the center.

map-main-view.jpg

Final Desired Result

First Attempt

At first, I looked into the IE specific functions onBeforePrint() and onAfterPrint() (which are also implemented in Firefox) to see if I could intercept the browser's print event and adjust the center position by half the difference between the original width and the print width. It did adjust the center position correctly, but for whatever reason the adjustment wasn't making it to the print preview window in time. The user would have to print, cancel and then print again to see the adjustment.

window.onbeforeprint = function() { 
	mapWidth = $('#map').width();
	
	if (mapWidth > 600)
	{
		var bounds = map.getBounds();
		var NE = bounds.getNorthEast();
		var SW = bounds.getSouthWest();
		
		var mapWidthRadians = NE.lng() - SW.lng();
		var radiansPerPixel = mapWidthRadians / mapWidth;
		
		var pixelShift = (mapWidth - 600) / 2;
		var radianShift = radiansPerPixel * pixelShift;
		
		var center = map.getCenter();
		var newCenter = new google.maps.LatLng(center.lat(), center.lng() + radianShift);
		
		map.setCenter(newCenter);
	}
}

Definitely a non-starter. Besides, it was highly browser specific so there had to be a better way.

The solution

The solution I eventually hit upon was to load 2 maps onto the page. One for viewing in the browser and one for the printer.

I have the following ids on each map: map and map-print. I then loaded a separate map with all the necessary markers for both.

Because Google Maps does not load correctly in a div with the style display: none;, I used the following styles:

In main.css:

#map { display: block; }
#map-print { visibility: hidden; position: absolute; }

In print.css:

#map { display: none; }
#map-print { visibility: visible; position: relative; }

This lets the print map take up space so it loads all the tiles correctly, but because of the absolute positioning it looks the same as a display: none;

Now that we have 2 maps with one visible to the browser and the other to the printer, we need to link them together so they maintain the same viewport:

var map, mapPrint;

function init() {

	/* Initialization code to load the 2 maps and anything else you need */

	google.maps.event.addListener(map, 'bounds_changed', boundsChanged);
}

function boundsChanged() 
{
	mapPrint.setCenter(map.getCenter());
	mapPrint.setZoom(map.getZoom());
}

Now the print map will track the center of the main map and reflect any changes in the zoom level.

Post a comment


(optional, will not be displayed)
If you can see this field, please leave it blank, or your comment will not be submitted
(optional)

Photo of Carl

About Carl

Web Programmer. Shutterbug. New Father. Enjoying life in New Zealand.

Read more

Facebook  LinkedIn  Twitter

Recent Activity

 

Photo Tags

Tags

Archives

Utilities