Place Photos

  • This sample demonstrates fetching and displaying photos for a specified place using the Google Maps JavaScript API.

  • It utilizes the Place class 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 
 : 
  
 2 
 px 
  
 solid 
  
 black 
 ; 
  
 border-radius 
 : 
  
 10 
 px 
 ; 
  
 padding 
 : 
  
 10 
 px 
 ; 
  
 max-width 
 : 
  
 950 
 px 
 ; 
  
 height 
 : 
  
 100 
 % 
 ; 
  
 max-height 
 : 
  
 400 
 px 
 ; 
  
 box-sizing 
 : 
  
 border-box 
 ; 
 } 
 . 
 place-overview 
  
 { 
  
 width 
 : 
  
 400 
 px 
 ; 
  
 height 
 : 
  
 380 
 px 
 ; 
  
 overflow-x 
 : 
  
 auto 
 ; 
  
 position 
 : 
  
 relative 
 ; 
  
 margin-right 
 : 
  
 20 
 px 
 ; 
 } 
 # 
 info 
  
 { 
  
 font-family 
 : 
  
 sans-serif 
 ; 
  
 position 
 : 
  
 sticky 
 ; 
  
 position 
 : 
  
 -webkit- 
 sticky 
 ; 
  
 left 
 : 
  
 0 
 ; 
  
 padding-bottom 
 : 
  
 10 
 px 
 ; 
 } 
 # 
 heading 
  
 { 
  
 width 
 : 
  
 500 
 px 
 ; 
  
 font-size 
 : 
  
 x-large 
 ; 
  
 margin-bottom 
 : 
  
 20 
 px 
 ; 
 } 
 # 
 summary 
  
 { 
  
 width 
 : 
  
 100 
 % 
 ; 
 } 
 # 
 gallery 
  
 { 
  
 display 
 : 
  
 flex 
 ; 
  
 padding-top 
 : 
  
 10 
 px 
 ; 
 } 
 # 
 gallery 
  
 img 
  
 { 
  
 width 
 : 
  
 200 
 px 
 ; 
  
 height 
 : 
  
 200 
 px 
 ; 
  
 margin 
 : 
  
 10 
 px 
 ; 
  
 border-radius 
 : 
  
 10 
 px 
 ; 
  
 cursor 
 : 
  
 pointer 
 ; 
  
 object-fit 
 : 
  
 cover 
 ; 
  
 /* fill the area without distorting the image */ 
 } 
 # 
 expanded-image 
  
 { 
  
 display 
 : 
  
 flex 
 ; 
  
 height 
 : 
  
 370 
 px 
 ; 
  
 overflow 
 : 
  
 hidden 
 ; 
  
 background-color 
 : 
  
 #000 
 ; 
  
 border-radius 
 : 
  
 10 
 px 
 ; 
  
 margin 
 : 
  
 0 
  
 auto 
 ; 
 } 
 . 
 attribution-label 
  
 { 
  
 background-color 
 : 
  
 rgba 
 ( 
 255 
 , 
  
 255 
 , 
  
 255 
 , 
  
 0.7 
 ); 
  
 font-size 
 : 
  
 10 
 px 
 ; 
  
 font-family 
 : 
  
 sans-serif 
 ; 
  
 margin 
 : 
  
 2 
 px 
 ; 
  
 position 
 : 
  
 absolute 
 ; 
 } 
 button 
  
 { 
  
 display 
 : 
  
 flex 
 ; 
  
 outline 
 : 
  
 none 
 ; 
  
 border 
 : 
  
 none 
 ; 
  
 padding 
 : 
  
 0 
 ; 
  
 background 
 : 
  
 none 
 ; 
  
 cursor 
 : 
  
 pointer 
 ; 
 } 
 button 
 : 
 focus 
  
 { 
  
 border 
 : 
  
 2 
 px 
  
 solid 
  
 blue 
 ; 
  
 border-radius 
 : 
  
 10 
 px 
 ; 
 } 
  

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.git 
 
  
  cd 
  
 samples 
 / 
 place 
 - 
 photos 
 
  
  npm 
  
 i 
 
  
  npm 
  
 start 
 
Create a Mobile Website
View Site in Mobile | Classic
Share by: