Stay organized with collections
Save and categorize content based on your preferences.
This rudimentary photo carousel displays photos for the specified place,
including the required author attributions (shown in the upper left corner of
the photo).
asyncfunctioninit(){const{Place}=awaitgoogle.maps.importLibrary('places')asgoogle.maps.PlacesLibrary;// Use a place ID to create a new Place instance.constplace=newPlace({id:'ChIJydSuSkkUkFQRsqhB-cEtYnw',// Woodland Park Zoo, Seattle WA});// Call fetchFields, passing the desired data fields.awaitplace.fetchFields({fields:['displayName','photos','editorialSummary']});// Get the various HTML elements.letheading=document.getElementById('heading')asHTMLElement;letsummary=document.getElementById('summary')asHTMLElement;letgallery=document.getElementById('gallery')asHTMLElement;letexpandedImageDiv=document.getElementById('expanded-image')asHTMLElement;letattributionLabel;// Show the display name and summary for the place.heading.textContent=place.displayNameasstring;summary.textContent=place.editorialSummaryasstring;// Add photos to the gallery.if(place.photos){place.photos?.forEach((photo)=>{constimg=document.createElement('img');constexpandedImage=document.createElement('img');img.src=photo.getURI({maxHeight:380});img.addEventListener('click',(event)=>{event.preventDefault();expandedImage.src=img.src;expandedImageDiv.innerHTML='';expandedImageDiv.appendChild(expandedImage);attributionLabel=createAttribution(photo.authorAttributions);expandedImageDiv.appendChild(attributionLabel);});gallery.appendChild(img);});}// Display the first photo.constimg=document.createElement('img');img.src=place.photos![0].getURI();expandedImageDiv.appendChild(img);attributionLabel=createAttribution(place.photos![0].authorAttributions);expandedImageDiv.appendChild(attributionLabel);// Helper function to create attribution DIV.functioncreateAttribution(attribution){attributionLabel=document.createElement("a");attributionLabel.classList.add('attribution-label');attributionLabel.textContent=attribution[0].displayName;attributionLabel.href=attribution[0].uri;attributionLabel.target='_blank;'returnattributionLabel;}}init();
asyncfunctioninit(){const{Place}=awaitgoogle.maps.importLibrary("places");// Use a place ID to create a new Place instance.constplace=newPlace({id:"ChIJydSuSkkUkFQRsqhB-cEtYnw",// Woodland Park Zoo, Seattle WA});// Call fetchFields, passing the desired data fields.awaitplace.fetchFields({fields:["displayName","photos","editorialSummary"],});// Get the various HTML elements.letheading=document.getElementById("heading");letsummary=document.getElementById("summary");letgallery=document.getElementById("gallery");letexpandedImageDiv=document.getElementById("expanded-image");letattributionLabel;// Show the display name and summary for the place.heading.textContent=place.displayName;summary.textContent=place.editorialSummary;// Add photos to the gallery.if(place.photos){place.photos?.forEach((photo)=>{constimg=document.createElement("img");constexpandedImage=document.createElement("img");img.src=photo.getURI({maxHeight:380});img.addEventListener("click",(event)=>{event.preventDefault();expandedImage.src=img.src;expandedImageDiv.innerHTML="";expandedImageDiv.appendChild(expandedImage);attributionLabel=createAttribution(photo.authorAttributions);expandedImageDiv.appendChild(attributionLabel);});gallery.appendChild(img);});}// Display the first photo.constimg=document.createElement("img");img.src=place.photos[0].getURI();expandedImageDiv.appendChild(img);attributionLabel=createAttribution(place.photos[0].authorAttributions);expandedImageDiv.appendChild(attributionLabel);// Helper function to create attribution DIV.functioncreateAttribution(attribution){attributionLabel=document.createElement("a");attributionLabel.classList.add("attribution-label");attributionLabel.textContent=attribution[0].displayName;attributionLabel.href=attribution[0].uri;attributionLabel.target="_blank;";returnattributionLabel;}}init();
/* * Always set the map height explicitly to define the size of the div element * that contains the map. */#map{height:100%;}/* * Optional: Makes the sample page fill the window. */html,body{height:100%;margin:0;padding:0;}#container{display:flex;padding:10px;width:100%;height:100%;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:500px;}#gallery{display:flex;}#galleryimg{width:200px;height:200px;margin-right:10px;margin-top:40px;border-radius:10px;cursor:pointer;}#expanded-image{display:flex;height:380px;overflow:hidden;background-color:#000;}#expanded-imageimg{width:100%;height:auto;object-fit:contain;}.attribution-label{background-color:#fff;opacity:0.7;font-size:10px;font-family:sans-serif;margin:2px;position:absolute;}
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.
[null,null,["Last updated 2025-08-28 UTC."],[[["\u003cp\u003eThis sample demonstrates fetching and displaying photos for a specified place using the Google Maps JavaScript API.\u003c/p\u003e\n"],["\u003cp\u003eIt utilizes the \u003ccode\u003ePlace\u003c/code\u003e class to retrieve place details, including photos and author attributions.\u003c/p\u003e\n"],["\u003cp\u003ePhotos are displayed in a rudimentary carousel with a larger view when clicked.\u003c/p\u003e\n"],["\u003cp\u003eAuthor attributions are included in the upper left corner of the photos.\u003c/p\u003e\n"],["\u003cp\u003eThe sample provides code in TypeScript, JavaScript, HTML, and CSS.\u003c/p\u003e\n"]]],["The core functionality is fetching and displaying place data, including photos, using the Google Maps API. A `Place` instance is created with a specific place ID, and its `displayName`, `photos`, and `editorialSummary` fields are retrieved. The place's name and summary are shown, and photo thumbnails are added to a gallery. Clicking a thumbnail displays the full-size image and author attribution in an expanded view.\n"],null,["This rudimentary photo carousel displays photos for the specified place,\nincluding the required author attributions (shown in the upper left corner of\nthe photo).\n\nRead the [documentation](/maps/documentation/javascript/place-photos). \n\nTypeScript \n\n```typescript\nasync function init() {\n const { Place } = await google.maps.importLibrary('places') as google.maps.PlacesLibrary;\n\n // Use a place ID to create a new Place instance.\n const place = new Place({\n id: 'ChIJydSuSkkUkFQRsqhB-cEtYnw', // Woodland Park Zoo, Seattle WA\n });\n\n // Call fetchFields, passing the desired data fields.\n await place.fetchFields({ fields: ['displayName', 'photos', 'editorialSummary'] });\n\n // Get the various HTML elements.\n let heading = document.getElementById('heading') as HTMLElement;\n let summary = document.getElementById('summary') as HTMLElement;\n let gallery = document.getElementById('gallery') as HTMLElement;\n let expandedImageDiv = document.getElementById('expanded-image') as HTMLElement;\n let attributionLabel;\n\n // Show the display name and summary for the place.\n heading.textContent = place.displayName as string;\n summary.textContent = place.editorialSummary as string;\n\n // Add photos to the gallery.\n if (place.photos) {\n place.photos?.forEach((photo) =\u003e {\n const img = document.createElement('img');\n const expandedImage = document.createElement('img');\n img.src = photo.getURI({maxHeight: 380});\n img.addEventListener('click', (event) =\u003e {\n event.preventDefault();\n expandedImage.src = img.src;\n expandedImageDiv.innerHTML = '';\n expandedImageDiv.appendChild(expandedImage);\n attributionLabel = createAttribution(photo.authorAttributions);\n expandedImageDiv.appendChild(attributionLabel);\n });\n\n gallery.appendChild(img);\n });\n }\n\n // Display the first photo.\n const img = document.createElement('img');\n img.src = place.photos![0].getURI();\n expandedImageDiv.appendChild(img);\n attributionLabel = createAttribution(place.photos![0].authorAttributions);\n expandedImageDiv.appendChild(attributionLabel);\n\n // Helper function to create attribution DIV.\n function createAttribution(attribution) {\n attributionLabel = document.createElement(\"a\");\n attributionLabel.classList.add('attribution-label');\n attributionLabel.textContent = attribution[0].displayName;\n attributionLabel.href = attribution[0].uri;\n attributionLabel.target = '_blank;'\n return attributionLabel;\n }\n}\n\ninit();https://github.com/googlemaps/js-samples/blob/2683f7366fb27829401945d2a7e27d77ed2df8e5/samples/place-photos/index.ts#L8-L67\n```\n| **Note:** Read the [guide](/maps/documentation/javascript/using-typescript) on using TypeScript and Google Maps.\n\nJavaScript \n\n```javascript\nasync function init() {\n const { Place } = await google.maps.importLibrary(\"places\");\n // Use a place ID to create a new Place instance.\n const place = new Place({\n id: \"ChIJydSuSkkUkFQRsqhB-cEtYnw\", // Woodland Park Zoo, Seattle WA\n });\n\n // Call fetchFields, passing the desired data fields.\n await place.fetchFields({\n fields: [\"displayName\", \"photos\", \"editorialSummary\"],\n });\n\n // Get the various HTML elements.\n let heading = document.getElementById(\"heading\");\n let summary = document.getElementById(\"summary\");\n let gallery = document.getElementById(\"gallery\");\n let expandedImageDiv = document.getElementById(\"expanded-image\");\n let attributionLabel;\n\n // Show the display name and summary for the place.\n heading.textContent = place.displayName;\n summary.textContent = place.editorialSummary;\n // Add photos to the gallery.\n if (place.photos) {\n place.photos?.forEach((photo) =\u003e {\n const img = document.createElement(\"img\");\n const expandedImage = document.createElement(\"img\");\n\n img.src = photo.getURI({ maxHeight: 380 });\n img.addEventListener(\"click\", (event) =\u003e {\n event.preventDefault();\n expandedImage.src = img.src;\n expandedImageDiv.innerHTML = \"\";\n expandedImageDiv.appendChild(expandedImage);\n attributionLabel = createAttribution(photo.authorAttributions);\n expandedImageDiv.appendChild(attributionLabel);\n });\n gallery.appendChild(img);\n });\n }\n\n // Display the first photo.\n const img = document.createElement(\"img\");\n\n img.src = place.photos[0].getURI();\n expandedImageDiv.appendChild(img);\n attributionLabel = createAttribution(place.photos[0].authorAttributions);\n expandedImageDiv.appendChild(attributionLabel);\n\n // Helper function to create attribution DIV.\n function createAttribution(attribution) {\n attributionLabel = document.createElement(\"a\");\n attributionLabel.classList.add(\"attribution-label\");\n attributionLabel.textContent = attribution[0].displayName;\n attributionLabel.href = attribution[0].uri;\n attributionLabel.target = \"_blank;\";\n return attributionLabel;\n }\n}\n\ninit();https://github.com/googlemaps/js-samples/blob/2683f7366fb27829401945d2a7e27d77ed2df8e5/dist/samples/place-photos/docs/index.js#L9-L69\n```\n| **Note:** The JavaScript is compiled from the TypeScript snippet.\n\nCSS \n\n```css\n/* \n * Always set the map height explicitly to define the size of the div element\n * that contains the map. \n */\n#map {\n height: 100%;\n}\n\n/* \n * Optional: Makes the sample page fill the window. \n */\nhtml,\nbody {\n height: 100%;\n margin: 0;\n padding: 0;\n}\n\n#container {\n display: flex;\n padding: 10px;\n width: 100%;\n height: 100%;\n box-sizing: border-box;\n}\n\n.place-overview {\n width: 400px;\n height: 380px;\n overflow-x: auto;\n position: relative;\n margin-right: 20px;\n}\n\n#info {\n font-family: sans-serif;\n position: sticky;\n position: -webkit-sticky;\n left: 0;\n padding-bottom: 10px;\n}\n\n#heading {\n width: 500px;\n font-size: x-large;\n margin-bottom: 20px;\n}\n\n#summary {\n width: 500px;\n}\n\n#gallery {\n display: flex;\n}\n\n#gallery img {\n width: 200px;\n height: 200px;\n margin-right: 10px;\n margin-top: 40px;\n border-radius: 10px;\n cursor: pointer;\n}\n\n#expanded-image {\n display: flex;\n height: 380px;\n overflow: hidden;\n background-color: #000;\n}\n\n#expanded-image img {\n width: 100%;\n height: auto;\n object-fit: contain;\n}\n\n.attribution-label {\n background-color: #fff;\n opacity: 0.7;\n font-size: 10px;\n font-family: sans-serif;\n margin: 2px;\n position: absolute;\n}\nhttps://github.com/googlemaps/js-samples/blob/2683f7366fb27829401945d2a7e27d77ed2df8e5/dist/samples/place-photos/docs/style.css#L7-L93\n```\n\nHTML \n\n```html\n\u003chtml\u003e\n \u003chead\u003e\n \u003ctitle\u003ePlace Photos\u003c/title\u003e\n\n \u003clink rel=\"stylesheet\" type=\"text/css\" href=\"./style.css\" /\u003e\n \u003cscript type=\"module\" src=\"./index.js\"\u003e\u003c/script\u003e\n \u003c/head\u003e\n \u003cbody\u003e\n \u003cdiv id=\"container\"\u003e\n \u003cdiv class=\"place-overview\"\u003e\n \u003cdiv id=\"info\"\u003e\n \u003cdiv id=\"heading\"\u003e\u003c/div\u003e\n \u003cdiv id=\"summary\"\u003e\u003c/div\u003e\n \u003c/div\u003e\n \u003cdiv id=\"gallery\"\u003e\u003c/div\u003e\n \u003c/div\u003e\n \u003cdiv id=\"expanded-image\"\u003e\u003c/div\u003e\n \u003c/div\u003e\n\n \u003c!-- prettier-ignore --\u003e\n \u003cscript\u003e(g=\u003e{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=()=\u003eh||(h=new Promise(async(f,n)=\u003e{await (a=m.createElement(\"script\"));e.set(\"libraries\",[...r]+\"\");for(k in g)e.set(k.replace(/[A-Z]/g,t=\u003e\"_\"+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=()=\u003eh=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)=\u003er.add(f)&&u().then(()=\u003ed[l](f,...n))})\n ({key: \"AIzaSyB41DRUbKWJHPxaFjMAwdrzWzbVKartNGg\", v: \"weekly\"});\u003c/script\u003e\n \u003c/body\u003e\n\u003c/html\u003ehttps://github.com/googlemaps/js-samples/blob/2683f7366fb27829401945d2a7e27d77ed2df8e5/dist/samples/place-photos/docs/index.html#L8-L31\n```\n\nTry Sample \n[JSFiddle.net](https://jsfiddle.net/gh/get/library/pure/googlemaps/js-samples/tree/master/dist/samples/place-photos/jsfiddle) [Google Cloud Shell](https://ssh.cloud.google.com/cloudshell/editor?cloudshell_git_repo=https%3A%2F%2Fgithub.com%2Fgooglemaps%2Fjs-samples&cloudshell_git_branch=sample-place-photos&cloudshell_tutorial=cloud_shell_instructions.md&cloudshell_workspace=.)\n\nClone Sample\n\n\nGit and Node.js are required to run this sample locally. Follow these [instructions](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm) to install Node.js and NPM. The following commands clone, install dependencies and start the sample application. \n\n git clone -b sample-place-photos https://github.com/googlemaps/js-samples.git\n cd js-samples\n npm i\n npm start\n\n\nOther samples can be tried by switching to any branch beginning with `sample-`\u003cvar translate=\"no\"\u003eSAMPLE_NAME\u003c/var\u003e. \n\n git checkout sample-\u003cvar translate=\"no\"\u003e\u003cspan class=\"devsite-syntax-nx\"\u003eSAMPLE_NAME\u003c/span\u003e\u003c/var\u003e\n npm i\n npm start"]]