OVERVIEW
One of the most useful features of Google Maps its ability to locate an address on the map. Geocoding is the process of taking a street address and finding its exact latitude and longitude, assuming the address is valid and exists in the Google database.
This article explains how to offer a realtime address location feature in a web page by typing in the address and capturing the resulting latitude and longitude in form fields.
I have avoided using any external javascript framework or library – this is just plain javascript and HTML which does the core functionality.
GOOGLE MAPS API KEY
It is assumed that you have already obtained a Google Maps API key which will be used within your page. If not then, you can obtain it from the Google API Console. The API key will be placed in your page as a script tag:
<script src="https://maps.googleapis.com/maps/api/js?key=xxxxxxxxxx&libraries=places" async defer></script>
Note that within the script tag we have added libraries=places parameter. This parameter activates the Google Places Library which enables the autocomplete feature as you type in an address.
SETTING UP THE HTML
The actual map will be displayed in a DIV with the id of smallmap. It is required that you set up at least the height and width of this DIV using CSS otherwise the map will not be displayed since it will default to zero height and width.
We define a form which contains three fields:
- location where you type in the address
- lat the latitude of the address which will come from Google Maps
- lng the longitude of the address which will come from Google Maps
The objective is to capture the values from the lat and lng field once we have an address. On successful location of an address we draw a marker on that spot in the map to mark the location. All the map logic is handled in javascript which is explained below:
THE JAVASCRIPT CODE
We define two global objects: map and geocoder. The entire map logic is within the initMap() function. This function is called when the page loads. We add a delay of a few milliseconds by using setTimeout() before calling the initMap() function. There is a practical reason for this. If you run your code right away, then depending on various network and browser factors, your code may execute before the Google Maps script has loaded into the browser, which will cause your code to fail. So we add a manual delay to let the Google Maps script finish loading before running our code.
When the map is created, we provide it with a default location to center on. In this case we have hardcoded the start position to be San Francisco as specified by thisLat, thisLng. We also set a default zoom level and the default maptype in mapOptions.
The geocoder object is then attached to the location text field in our form by creating the Google Places Autocomplete object and binding it to the location text field.
The object is to show a marker at the geolocated position on the top. For that purpose we can setup our own custom icon as the marker instead of the default Google pin. The icon object is created, but in this example we are not using it. The url property will point to the graphic file that contains the icon to be shown.
For the custom icon to be used, it is assigned to the icon property when creating our marker object. In this example that part is commented out. It can be enabled if required.
Now we add a place_changed listener to our autocomplete object. If an address is located, then we
- Zoom the map
- Center it on the address
- Obtain the latitude and longitude and store it in the form fields.
- Put the marker on that location in the map
- Create an infowindow on that marker and open it
SCREENSHOT
This is how the map looks after a successful geocoding.
THE SOURCE
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0"> <title>Google Maps Geocoding Test</title> <style> #smallmap { height:400px; width:800px;} </style> </head> <body> <form name=frmProd id=frmProd> <br><br> <input name="location" id="location" maxlength=255 size=100> <br><br> Lat: <input id="xlat" name="xlat" size=20> Lng <input id="xlng" name="xlng" size=20> <br><br> <div id="smallmap"></div> <br> <button type="submit" id="btnSubmit">Save</button> </form> <script src="https://maps.googleapis.com/maps/api/js?key=xxxxxxxxxxxxxxx&libraries=places" async defer></script> <script> setTimeout( initMap, 2000); var map=null; var geocoder=null; var location_lat =0; var location_lng = 0; var thislat = null; var thislng = null; function initMap() { if (thislat == null) thislat = 37.7749; if (thislng == null) thislng = -122.4194; var myLatlng = new google.maps.LatLng(thislat, thislng); var mapOptions = { zoom: 15, center: myLatlng, mapTypeId: 'roadmap' }; map = new google.maps.Map(document.getElementById('smallmap'), mapOptions); geocoder = new google.maps.Geocoder(); var input = document.getElementById("location"); var autocomplete = new google.maps.places.Autocomplete(input); autocomplete.bindTo("bounds", map); var infowindow = new google.maps.InfoWindow(); var icon = { url: 'images/google-pin.png', // url scaledSize: new google.maps.Size(50, 50), // scaled size origin: new google.maps.Point(0,0), // origin anchor: new google.maps.Point(0, 0) // anchor }; var marker = new google.maps.Marker({ map: map, anchorPoint: new google.maps.Point(0, -29) //,icon: icon }); autocomplete.addListener('place_changed', function() { infowindow.close(); marker.setVisible(false); var place = autocomplete.getPlace(); if (!place.geometry) { window.alert("Google Maps cannot recognize this address."); return; } // If the place has a geometry, then present it on a map. if (place.geometry.viewport) { map.fitBounds(place.geometry.viewport); } else { map.setCenter(place.geometry.location); map.setZoom(17); // Why 17? Because it looks good. } location_lat = place.geometry.location.lat(); location_lng = place.geometry.location.lng(); document.frmProd.xlat.value = location_lat; document.frmProd.xlng.value = location_lng; marker.setPosition(place.geometry.location); marker.setVisible(true); var address = ''; if (place.address_components) { address = [ (place.address_components[0] && place.address_components[0].short_name || ''), (place.address_components[1] && place.address_components[1].short_name || ''), (place.address_components[2] && place.address_components[2].short_name || '') ].join(' '); } infowindow.setContent('<div><strong>' + place.name + '</strong><br>' + address); infowindow.open(map, marker); }); } </script> </body> </html>
Leave a Reply