In the last post we looked at a basic implementation of a round-the-world itinerary in Google Maps. In today’s post we’re going to add the ability to see the first photo associated with a location when you click on it.
The Google Maps API makes it fairly easy to get the photos associated with a particular place, but it helps to identify that place uniquely: while you can search for a place based on its name, it’s more efficient and reliable to get its unique “place ID” and use that instead. I used this handy PlaceD Finder tool to get the IDs associated with our various destinations and went and added them to our array.
Then it was a fairly simple matter of using the PlacesService to get the place description which includes an array of any photos associated with the place. We can then have an img element in our “info window” point at the first photo in the list.
Here’s the updated code:
<html>
<head>
<style>
html,
body {
padding: 0;
margin: 0;
}
#map {
height: 100%;
width: 100%;
overflow: hidden;
float: left;
border: thin solid #333;
}
h3 {
margin: 0 0 5px 0;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
p {
margin: 0 0 10px 0;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
</style>
</head>
<body>
<div id="map"></div>
<script async defer src="https://maps.googleapis.com/maps/api/js?key=[ENTER_YOUR_KEY_HERE]&libraries=places&callback=initMap"></script>
<script type='text/javascript'>
var map;
var infowindow;
var service;
// Data for the markers consisting of a name, a LatLng and a zIndex for the
// order in which these markers should display on top of each other.
var stops = [
['Marin-Epagnier', 'ChIJt4RhN0UJjkcR9dxtPHTvIRY', 47.0091808, 7.0015896, 1],
['Washington', 'ChIJW-T2Wt7Gt4kRKl2I1CJFUsI', 38.9071923, -77.0368707, 2],
['New York', 'ChIJOwg_06VPwokRYv534QaPC8g', 40.7127837, -74.0059413, 3],
['West Hartford', 'ChIJ_RQEifWs54kRfDtRDlPX-Wc', 41.7620842, -72.7420151, 4],
['Boston', 'ChIJGzE9DS1l44kRoOhiASS_fHg', 42.3600825, -71.0588801, 5],
['Toronto', 'ChIJpTvG15DL1IkRd8S0KlBVNTI', 43.653226, -79.3831843, 6],
['Bozeman', 'ChIJE4i6T0xERVMRqmA792TQ9WM', 45.6769979, -111.0429339, 7],
['Yellowstone National Park', 'ChIJVVVVVVXlUVMRu-GPNDD5qKw', 44.427963, -110.588455, 8],
['Grand Teton National Park', 'ChIJqRtdyZ5RUlMRN6ORzI64oKU', 43.7904282, -110.6817627, 9],
['Salt Lake City', 'ChIJ7THRiJQ9UocRyjFNSKC3U1s', 40.7607793, -111.8910474, 10],
['Bryce Canyon', 'ChIJbUw47h9pNYcRYv1Jemw3nHU', 37.6283161, -112.1676947, 11],
['Zion National Park', 'ChIJ2fhEiNDqyoAR9VY2qhU6Lnw', 37.2982022, -113.0263005, 12],
['Las Vegas', 'ChIJ0X31pIK3voARo3mz1ebVzDo', 36.1699412, -115.1398296, 13],
['Death Valley', 'ChIJsf-PHqI5x4ARJd0j14NziRw', 36.5322649, -116.9325408, 14],
['Sequoia National Park', 'ChIJeWUZLX37v4ARZPQen_nfCkQ', 36.4863668, -118.5657516, 15],
['Big Sur', 'ChIJVVikTfuPjYARYuO38cfXpRY', 36.2704212, -121.807976, 16],
['Monterey', 'ChIJkfu1cFLkjYARXj1K2AlJSO4', 36.6002378, -121.8946761, 17],
['San Francisco', 'ChIJIQBpAG2ahYAR_6128GcTUEo', 37.7749295, -122.4194155, 18],
['Lima', 'ChIJ3-EpLOzDBZERRBEzku1Ooak', -12.0463667, -77.0427891, 19],
['Machu Picchu', 'ChIJVVVViV-abZERJxqgpA43EDo', -13.1631412, -72.5449629, 20],
['Cusco', 'ChIJMYRZJtjVbZERXTEYI8yWqSo', -13.53195, -71.9674626, 21],
['São Paulo', 'ChIJ0WGkg4FEzpQRrlsz_whLqZs', -23.5505199, -46.6333094, 22],
['Rio de Janeiro', 'ChIJW6AIkVXemwARTtIvZ2xC3FA', -22.9068467, -43.1728965, 23],
['Iguazu Falls', 'ChIJbRuqowzq9pQRfphenBd1e5E', -25.695259, -54.4388549, 24],
['Córdoba', 'ChIJaVuPR1-YMpQRkrBmU5pPorA', -31.4200833, -64.1887761, 25],
['Parque Nacional Talampaya', 'ChIJUUxbf6rPgpYRaEkBxpGDANQ', -29.8906226, -67.853468, 26],
['Valle de la Luna', 'ChIJ33tfOKhoLZQRTn9HuPJlE5g', -22.9257639, -68.2879926, 27],
['Catamarca', 'ChIJzZ8PHb8oJJQRGoYJFkvdHn4', -28.469581, -65.7795441, 28],
['San Miguel de Tucumán', 'ChIJA2nF1pI3IpQRJ2XFtZJbjfg', -26.8082848, -65.2175903, 29],
['Salta', 'ChIJ-bdRUaPDG5QRBvKH1SyZzaU', -24.7821269, -65.4231976, 30],
['Salar de Uyuni', 'ChIJh9rdHuC6_5MRkFuFng0T5RI', -20.1595348, -67.4054025, 31],
['San Pedro de Atacama', 'ChIJP78qqXpMqJYR0Zf5rExh9Ho', -22.9087073, -68.1997156, 32],
['Pan de Azúcar National Park', 'ChIJM6BM4cewvJYRbC7GcVat_6U', -26.177565, -70.5495396, 33],
['Raúl Marine Balmaceda', 'ChIJ4V-JqObIkZYRiGptmZGVUn8', -29.9695076, -71.3416309, 34],
['Santiago', 'ChIJuzrymgbQYpYRl0jtCfRZnYc', -33.4378305, -70.6504492, 35],
['Easter Island', 'ChIJK67UqBfwR5kRti0qwO2z5bs', -27.112723, -109.3496865, 36],
['Tahiti', 'ChIJTddtfNB1GHQREVfDCXp6wJs', -17.6509195, -149.4260421, 37],
['Auckland', 'ChIJ--acWvtHDW0RF5miQ2HvAAU', -36.8484597, 174.7633315, 38],
['Rotorua', 'ChIJK7L2gj2Ybm0RMZmjQ2HvAAU', -38.1368478, 176.2497461, 39],
['Wellington', 'ChIJy3TpSfyxOG0RcLQTomPvAAo', -41.2864603, 174.776236, 40],
['Paparoa National Park', 'ChIJbZoxICBxJW0RIPF5hIbvAAU', -42.1632433, 171.366731, 41],
['Queenstown', 'ChIJX96o1_Ed1akRAKZ5hIbvAAU', -45.0311622, 168.6626435, 42],
['Sydney', 'ChIJP5iLHkCuEmsRwMwyFmh9AQU', -33.8688197, 151.2092955, 43],
['Brisbane', 'ChIJM9KTrJpXkWsRQK_e81qjAgQ', -27.4697707, 153.0251235, 44],
['Cairns', 'ChIJEySiW1VieGkRYHggf_HuAAQ', -16.9185514, 145.7780548, 45],
['Kuala Lumpur', 'ChIJ5-rvAcdJzDERfSgcL1uO2fQ', 3.139003, 101.686855, 46],
['Singapore', 'ChIJdZOLiiMR2jERxPWrUs9peIg', 1.352083, 103.819836, 47],
['Coimbatore', 'ChIJtRyXL69ZqDsRgtI-GB7IwS8', 11.0168445, 76.9558321, 48],
['Kodaikanal', 'ChIJhwMKf2NmBzsRPMFYNzfp-p8', 10.2381136, 77.4891822, 49],
['Bangalore', 'ChIJbU60yXAWrjsR4E9-UejD3_g', 12.9715987, 77.5945627, 50],
['Durban', 'ChIJt2G8AQCq9x4RgW6qxEZVp8w', -29.8586804, 31.0218404, 51],
['Lesotho', 'ChIJ64xf1idIjB4Rsx7ReLhXLSM', -29.609988, 28.233608, 52],
['Addo Elephant National Park', 'ChIJY2nuzYRPex4RCsT--8cm454', -33.4833333, 25.75, 53],
['Tsitsikamma', 'ChIJaTwmTQ5ueR4R5_kNGLX6RBs', -32.2178721, 26.5772048, 54],
['Knysna', 'ChIJ2QwBlkDqeB4Rzc5QdeG5Kr4', -34.0350856, 23.0464693, 55],
['Oudtshoorn', 'ChIJtRO16obB1R0RYesIjnRHQ40', -33.6007225, 22.2026347, 56],
['Franschhoek', 'ChIJz7IFaAe9zR0R-bJW01SGtDw', -33.8974833, 19.1523292, 57],
['Stellenbosch', 'ChIJpeKIUfeyzR0R4mvj3gCqCXA', -33.9321045, 18.860152, 58],
['Cape Town', 'ChIJ1-4miA9QzB0Rh6ooKPzhf2g', -33.9248685, 18.4240553, 59]
];
function initMap() {
map = new google.maps.Map(document.getElementById('map'), {
center: new google.maps.LatLng(15, -30),
zoom: 2,
mapTypeId: 'satellite'
});
infowindow = new google.maps.InfoWindow();
service = new google.maps.places.PlacesService(map);
setMarkers(map);
}
function setMarkers(map) {
// Adds markers to the map with a delay
var delay = 100;
for (var i = 0; i <= stops.length; i++) {
var timeout = i * delay;
// If this is the last segment, just add the line
if (i === stops.length) {
addConnectingLineWithTimeout(stops[i - 1], stops[0], timeout + delay);
} else if (i >= 0) {
// Otherwise add a marker after a delay, followed by the
// connecting line to the previous marker, if there is one
addMarkerWithTimeout(stops[i], timeout);
if (i > 0) {
addConnectingLineWithTimeout(stops[i], stops[i - 1], timeout + delay);
}
}
}
}
function addMarkerWithTimeout(stop, timeout) {
setTimeout(function() {
var marker = new google.maps.Marker({
map: map,
title: stop[0],
placeId: stop[1],
position: {
lat: stop[2],
lng: stop[3]
},
label: stop[4].toString(),
zIndex: stop[4]
//animation: google.maps.Animation.DROP, // Cool but too much
});
// Register the callback for when the marker is clicked
google.maps.event.addListener(marker, 'click', function() {
onItemClick(event, marker);
});
}, timeout);
}
function addLabelWithTimeout(lat, long, text, timeout) {
setTimeout(function() {
var pos = new google.maps.LatLng(lat, long);
var mapLabel = new MapLabel({
text: text,
position: pos,
map: map,
fontSize: 14
});
mapLabel.set('position', new google.maps.LatLng(lat, long));
}, timeout);
}
function addConnectingLineWithTimeout(stop1, stop2, timeout) {
setTimeout(function() {
var flightPath = new google.maps.Polyline({
path: [{
lat: stop1[2],
lng: stop1[3]
}, {
lat: stop2[2],
lng: stop2[3]
}],
geodesic: true,
strokeColor: '#D34038',
strokeOpacity: 1.0,
strokeWeight: 4
});
flightPath.setMap(map);
}, timeout);
}
// Info window trigger function
function onItemClick(event, pin) {
service.getDetails({
placeId: pin.placeId
}, function(place, status) {
var cont =
'<div><h3>' + place.name + '</h3><p>' + place.formatted_address + '</p>' +
(place.photos && place.photos.length > 0 ?
('<img src="' +
place.photos[0].getUrl({
'maxWidth': 300,
'maxHeight': 200
}) + '" />') : '') +
'</div>'
infowindow.setContent(cont);
infowindow.open(map, pin);
});
}
</script>
</body>
</html>
Here’s a picture of what our map now looks like once one of our placemarkers has been clicked:
Try it for yourself here:
Next time we’ll look at placing labels on the map to indicate the month of travel. I’ll be posting from Washington D.C. which is the first official stop on our trip, if you don’t include a pub lunch in London between flights on Sunday. Here we go!