Page Summary
-
This sample demonstrates fetching and displaying photos for a specified place using the Google Maps JavaScript API.
-
It utilizes the
Placeclass to retrieve place details, including photos and author attributions. -
Photos are displayed in a rudimentary carousel with a larger view when clicked.
-
Author attributions are included in the upper left corner of the photos.
-
The sample provides code in TypeScript, JavaScript, HTML, and CSS.
This rudimentary photo carousel displays photos for the specified place, including the required author attributions (shown in the upper left corner of the photo).
Read the documentation.
TypeScript
async function init() { const { Place } = (await google.maps.importLibrary( 'places' )) as google.maps.PlacesLibrary; // Use a place ID to create a new Place instance. const place = new Place({ id: 'ChIJydSuSkkUkFQRsqhB-cEtYnw', // Woodland Park Zoo, Seattle WA }); // Call fetchFields, passing the desired data fields. await place.fetchFields({ fields: ['displayName', 'photos', 'editorialSummary'], }); // Get the various HTML elements. const heading = document.getElementById('heading') as HTMLElement; const summary = document.getElementById('summary') as HTMLElement; const gallery = document.getElementById('gallery') as HTMLElement; const expandedImageDiv = document.getElementById( 'expanded-image' ) as HTMLElement; // Show the display name and summary for the place. heading.textContent = place.displayName as string; summary.textContent = place.editorialSummary as string; // Add photos to the gallery. place.photos?.forEach((photo) => { const altText = 'Photo of ' + place.displayName; const img = document.createElement('img'); const imgButton = document.createElement('button'); const expandedImage = document.createElement('img'); img.src = photo?.getURI({ maxHeight: 380 }); img.alt = altText; imgButton.addEventListener('click', (event) => { centerSelectedThumbnail(imgButton); event.preventDefault(); expandedImage.src = img.src; expandedImage.alt = altText; expandedImageDiv.innerHTML = ''; expandedImageDiv.appendChild(expandedImage); const attributionLabel = createAttribution( photo.authorAttributions[0] )!; expandedImageDiv.appendChild(attributionLabel); }); imgButton.addEventListener('focus', () => { centerSelectedThumbnail(imgButton); }); imgButton.appendChild(img); gallery.appendChild(imgButton); }); // Display the first photo. if (place.photos && place.photos.length > 0) { const photo = place.photos[0]; const img = document.createElement('img'); img.alt = 'Photo of ' + place.displayName; img.src = photo.getURI(); expandedImageDiv.appendChild(img); if (photo.authorAttributions && photo.authorAttributions.length > 0) { expandedImageDiv.appendChild( createAttribution(photo.authorAttributions[0]) ); } } // Helper function to create attribution DIV. function createAttribution( attribution: google.maps.places.AuthorAttribution ) { const attributionLabel = document.createElement('a'); attributionLabel.classList.add('attribution-label'); attributionLabel.textContent = attribution.displayName; attributionLabel.href = attribution.uri!; attributionLabel.target = '_blank'; attributionLabel.rel = 'noopener noreferrer'; return attributionLabel; } // Helper function to center the selected thumbnail in the gallery. function centerSelectedThumbnail(element: HTMLElement) { element.scrollIntoView({ behavior: 'smooth', block: 'center', inline: 'center', }); } } init();
JavaScript
async function init() { const { Place } = (await google.maps.importLibrary('places')); // Use a place ID to create a new Place instance. const place = new Place({ id: 'ChIJydSuSkkUkFQRsqhB-cEtYnw', // Woodland Park Zoo, Seattle WA }); // Call fetchFields, passing the desired data fields. await place.fetchFields({ fields: ['displayName', 'photos', 'editorialSummary'], }); // Get the various HTML elements. const heading = document.getElementById('heading'); const summary = document.getElementById('summary'); const gallery = document.getElementById('gallery'); const expandedImageDiv = document.getElementById('expanded-image'); // Show the display name and summary for the place. heading.textContent = place.displayName; summary.textContent = place.editorialSummary; // Add photos to the gallery. place.photos?.forEach((photo) => { const altText = 'Photo of ' + place.displayName; const img = document.createElement('img'); const imgButton = document.createElement('button'); const expandedImage = document.createElement('img'); img.src = photo?.getURI({ maxHeight: 380 }); img.alt = altText; imgButton.addEventListener('click', (event) => { centerSelectedThumbnail(imgButton); event.preventDefault(); expandedImage.src = img.src; expandedImage.alt = altText; expandedImageDiv.innerHTML = ''; expandedImageDiv.appendChild(expandedImage); const attributionLabel = createAttribution(photo.authorAttributions[0]); expandedImageDiv.appendChild(attributionLabel); }); imgButton.addEventListener('focus', () => { centerSelectedThumbnail(imgButton); }); imgButton.appendChild(img); gallery.appendChild(imgButton); }); // Display the first photo. if (place.photos && place.photos.length > 0) { const photo = place.photos[0]; const img = document.createElement('img'); img.alt = 'Photo of ' + place.displayName; img.src = photo.getURI(); expandedImageDiv.appendChild(img); if (photo.authorAttributions && photo.authorAttributions.length > 0) { expandedImageDiv.appendChild(createAttribution(photo.authorAttributions[0])); } } // Helper function to create attribution DIV. function createAttribution(attribution) { const attributionLabel = document.createElement('a'); attributionLabel.classList.add('attribution-label'); attributionLabel.textContent = attribution.displayName; attributionLabel.href = attribution.uri; attributionLabel.target = '_blank'; attributionLabel.rel = 'noopener noreferrer'; return attributionLabel; } // Helper function to center the selected thumbnail in the gallery. function centerSelectedThumbnail(element) { element.scrollIntoView({ behavior: 'smooth', block: 'center', inline: 'center', }); } } init();
CSS
/* * Optional: Makes the sample page fill the window. */ html, body { height: 100%; margin: 0; padding: 0; } #container { display: flex; border: 2px solid black; border-radius: 10px; padding: 10px; max-width: 950px; height: 100%; max-height: 400px; box-sizing: border-box; } .place-overview { width: 400px; height: 380px; overflow-x: auto; position: relative; margin-right: 20px; } #info { font-family: sans-serif; position: sticky; position: -webkit-sticky; left: 0; padding-bottom: 10px; } #heading { width: 500px; font-size: x-large; margin-bottom: 20px; } #summary { width: 100%; } #gallery { display: flex; padding-top: 10px; } #gallery img { width: 200px; height: 200px; margin: 10px; border-radius: 10px; cursor: pointer; object-fit: cover; /* fill the area without distorting the image */ } #expanded-image { display: flex; height: 370px; overflow: hidden; background-color: #000; border-radius: 10px; margin: 0 auto; } .attribution-label { background-color: rgba(255, 255, 255, 0.7); font-size: 10px; font-family: sans-serif; margin: 2px; position: absolute; } button { display: flex; outline: none; border: none; padding: 0; background: none; cursor: pointer; } button:focus { border: 2px solid blue; border-radius: 10px; }
HTML
<html lang="en">
<head>
<title>Place Photos</title>
<link rel="stylesheet" type="text/css" href="./style.css" />
<script type="module" src="./index.js"></script>
<!-- prettier-ignore -->
<script>(g => { var h, a, k, p = "The Google Maps JavaScript API", c = "google", l = "importLibrary", q = "__ib__", m = document, b = window; b = b[c] || (b[c] = {}); var d = b.maps || (b.maps = {}), r = new Set, e = new URLSearchParams, u = () => h || (h = new Promise(async (f, n) => { await (a = m.createElement("script")); e.set("libraries", [...r] + ""); for (k in g) e.set(k.replace(/[A-Z]/g, t => "_" + t[0].toLowerCase()), g[k]); e.set("callback", c + ".maps." + q); a.src = `https://maps.${c}apis.com/maps/api/js?` + e; d[q] = f; a.onerror = () => h = n(Error(p + " could not load.")); a.nonce = m.querySelector("script[nonce]")?.nonce || ""; m.head.append(a) })); d[l] ? console.warn(p + " only loads once. Ignoring:", g) : d[l] = (f, ...n) => r.add(f) && u().then(() => d[l](f, ...n)) })
({ key: "AIzaSyA6myHzS10YXdcazAFalmXvDkrYCp5cLc8", v: "weekly" });</script>
</head>
<body>
<div id="container">
<div class="place-overview">
<div id="info">
<h1 id="heading"></h1>
<div id="summary"></div>
</div>
<div id="gallery"></div>
</div>
<div id="expanded-image"></div>
</div>
</body>
</html>Try Sample
Clone Sample
Git and Node.js are required to run this sample locally. Follow these instructions to install Node.js and NPM. The following commands clone, install dependencies and start the sample application.
git clone https://github.com/googlemaps-samples/js-api-samples.gitcd samples/place-photosnpm inpm start