Earlier this morning I was building a Google Map demo for a client (using EventBrite data - I'll share that if I can) and I needed to center a Google Map on America. There are a couple ways of doing this and I thought I'd share them along with some screen shots so you can see the results.
The first Google result I found led to this Stack Overflow result: How to center Google Map on a country by name. The answer uses Geocoding to translate a simple country name, like America, into the right results. You'll need to scroll down a bit to see a version of the code for the current version of Google's API, or just check out the full sample below.
<!DOCTYPE html>
<html>
<head>
<title>Demo One</title>
<style type="text/css">
#map_canvas { width: 500px; height: 500px; }
</style>
<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script>
<script type="text/javascript">
function initialize() {
var country = "United States"
var myOptions = {
zoom: 3,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
var map = new google.maps.Map(document.getElementById("map_canvas"),myOptions);
var geocoder = new google.maps.Geocoder();
geocoder.geocode( { 'address': country }, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
map.setCenter(results[0].geometry.location);
} else {
alert("Could not find location: " + location);
}
});
}
</script>
</head>
<body onload="initialize()">
<div id="map_canvas"></div>
</body>
</html>
This gives you:
Looks good to me - but the geocoding bugs me. For every single visitor to your site, a request will be made to Google to ask it where America is. Most likely, America is not going to move. Probably. And while this request is pretty darn fast, there's no real reason for you to geocode this constantly. I did another quick Google and discovered this Wikipedia page: Geographic center of the contiguous United States. It defined the longitude and latitude for America as 39°50?N 98°35?W. I rewrote my code to simply use these hard coded values.
<!DOCTYPE html>
<html>
<head>
<title>Demo Two</title>
<style type="text/css">
#map_canvas { width: 500px; height: 500px; }
</style>
<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script>
<script type="text/javascript">
function initialize() {
var latlng = new google.maps.LatLng(39.5, -98.35);
var myOptions = {
zoom: 3,
center: latlng,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
var map = new google.maps.Map(document.getElementById("map_canvas"),myOptions);
}
</script>
</head>
<body onload="initialize()">
<div id="map_canvas"></div>
</body>
</html>
And the result:
Looks a tiny bit different to me. So I went back to the first demo and added this line: console.log(results[0].geometry.location.lat(), results[0].geometry.location.lng());
. I checked the console for the values and simply updated the numbers.
I zipped up the demos (including a third demo with the values returned via the console) and included it as a zip.
Archived Comments
That second result must be the result of continental drift! https://en.wikipedia.org/wi...
I've played around a bit with this script and actually implemented it on several websites. The location of choice is good with me. Learned some new thing's from you as usual. You definitely helped connect the dots on several thing's. I created the same code and placed it into a CF file for inclusion.
Hi Raymond,
apologies up front for the shameless self-promotion. I'm the product manager for the HERE Geocoder and I stumbled across your post. In HERE Geocoder we're offering a map view bounding box as part of the response. I wonder whether that would help solve your problem better. You could scale the map display with the screen size and still ensure America is fully visible.
Here is an example of the response and the API call:
http://geocoder.cit.api.her...
{
relevance: 1,
matchLevel: "country",
matchQuality: {
country: 1
},
location: {
locationId: "02wVnFKLeuA57le7GuahvD",
locationType: "area",
displayPosition: {
latitude: 38.89037,
longitude: -77.03196
},
navigationPosition: [
{
latitude: 38.89037,
longitude: -77.03196
}
],
mapView: {
topLeft: {
latitude: 49.3845,
longitude: -124.749
},
bottomRight: {
latitude: 24.5018,
longitude: -66.9406
}
},
address: {
label: "United States",
country: "USA",
additionalData: [
{
value: "United States",
key: "CountryName"
}
]
},
mapReference: {
mapVersion: "Q2/2014",
countryId: "21000001"
}
},
matchCode: "exact"
}
First off - nope - I don't mind you mentioning your product, especially since you were honest about it. ;)
I dont believe - however - that my issue was with the bounding box per se. I just wanted to center on America and wanted the quickest solution for that. Which to me was to Geocode *once* and copy the values. I'll point out that the Google Geocde API also does this for results. (I forget the name though - they don't call it a bounding box but it has a similar result.) Although your JSON looks to be a lot more clearer about it.
Thanks for your feedback Raymond. I was thinking a mapView maybe helpful in getting the zoom level right.
And since our service sets the display coordinate for the USA into the center of Washington DC, I thought maybe Google does the same. But you are right, the have what they call a "viewport" and this is similar to our mapView. And their display coordinate is actually centered, somewhere in Kansas.
Could it be that the difference comes from 39°50"N 98°35W is not 39,5 and -98,35 but rather 39+50/60 and -98-35/60?
Probably. :) How would you have changed 39/50 to decimal?
I think there are 60 minutes to 1 degree, and 60 seconds to 1 minute (cf. http://astro.unl.edu/naap/m...
Therefore, 39°50"N should be 39+50/60 which is about 39,833 and 98°35"W should be -98-35/60 which is about -98,583 (reading further down in the Wikipedia article you cite for the location, you'll find: "Modern methodology has identified the location as Latitude 39.828127, Longitude -98.579404") which is almost exactly the values obtained when converting the long/lat to decimal. HTH :)
Ah that does make sense. Thanks. :)
Glad I took a look at the page you posted a link too Thomas. Had no clue about the conversion method used above...