Place Photos позволяет добавлять высококачественный фотоконтент на ваши веб-страницы. Получите доступ к миллионам фотографий, хранящихся в базе данных Places, и используйте функции изменения размера изображений: «Найти место», «Поиск поблизости», «Текстовый поиск», «Автозаполнение» и «Подробная информация о месте».
См. полный пример исходного кода.
В этой демонстрации отображается случайная фотография из одного из пяти городов, а в правом нижнем углу фотографии указывается необходимое авторство.
Машинопись
const CITIES = [ { name: 'New York', id: 'ChIJOwg_06VPwokRYv534QaPC8g' }, { name: 'London', id: 'ChIJdd4hrwug2EcRmSrV3Vo6llI' }, { name: 'Paris', id: 'ChIJD7fiBh9u5kcRYJSMaMOCCwQ' }, { name: 'Tokyo', id: 'ChIJ51cu8IcbXWARiRtXIothAS4' }, { name: 'Rome', id: 'ChIJu46S-ZZhLxMROG5lkwZ3D7k' }, ]; async function init() { const { Place } = await google.maps.importLibrary('places'); const heading = document.getElementById('heading')!; const summary = document.getElementById('summary')!; const expandedImageDiv = document.getElementById('expanded-image')!; const randomizeBtn = document.getElementById( 'randomize-btn' ) as HTMLButtonElement; async function showRandomCityPhoto() { randomizeBtn.disabled = true; // Pick a random city const city = CITIES[Math.floor(Math.random() * CITIES.length)]; try { const place = new Place({ id: city.id }); await place.fetchFields({ fields: ['displayName', 'photos', 'editorialSummary'], }); heading.textContent = place.displayName ?? city.name; summary.textContent = place.editorialSummary ?? ''; expandedImageDiv.innerHTML = ''; if (place.photos && place.photos.length > 0) { // Pick one of the first 10 photos const maxPhotos = Math.min(10, place.photos.length); const randomIndex = Math.floor(Math.random() * maxPhotos); const photo = place.photos[randomIndex]; const img = document.createElement('img'); img.alt = `Photo of ${place.displayName ?? city.name}`; img.src = photo.getURI({ maxHeight: 800 }); expandedImageDiv.appendChild(img); if (photo.authorAttributions.length) { expandedImageDiv.appendChild( createAttribution(photo.authorAttributions[0]) ); } } else { expandedImageDiv.textContent = 'No photos available for this location.'; } } catch (error) { console.error('Failed to fetch place details:', error); summary.textContent = 'Failed to load data.'; } // Re-enable button after 2 seconds setTimeout(() => { randomizeBtn.disabled = false; }, 2000); } // 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; } randomizeBtn.addEventListener('click', () => void showRandomCityPhoto()); // Initial load void showRandomCityPhoto(); } void init();
JavaScript
const CITIES = [ { name: 'New York', id: 'ChIJOwg_06VPwokRYv534QaPC8g' }, { name: 'London', id: 'ChIJdd4hrwug2EcRmSrV3Vo6llI' }, { name: 'Paris', id: 'ChIJD7fiBh9u5kcRYJSMaMOCCwQ' }, { name: 'Tokyo', id: 'ChIJ51cu8IcbXWARiRtXIothAS4' }, { name: 'Rome', id: 'ChIJu46S-ZZhLxMROG5lkwZ3D7k' }, ]; async function init() { const { Place } = await google.maps.importLibrary('places'); const heading = document.getElementById('heading'); const summary = document.getElementById('summary'); const expandedImageDiv = document.getElementById('expanded-image'); const randomizeBtn = document.getElementById('randomize-btn'); async function showRandomCityPhoto() { randomizeBtn.disabled = true; // Pick a random city const city = CITIES[Math.floor(Math.random() * CITIES.length)]; try { const place = new Place({ id: city.id }); await place.fetchFields({ fields: ['displayName', 'photos', 'editorialSummary'], }); heading.textContent = place.displayName ?? city.name; summary.textContent = place.editorialSummary ?? ''; expandedImageDiv.innerHTML = ''; if (place.photos && place.photos.length > 0) { // Pick one of the first 10 photos const maxPhotos = Math.min(10, place.photos.length); const randomIndex = Math.floor(Math.random() * maxPhotos); const photo = place.photos[randomIndex]; const img = document.createElement('img'); img.alt = `Photo of ${place.displayName ?? city.name}`; img.src = photo.getURI({ maxHeight: 800 }); expandedImageDiv.appendChild(img); if (photo.authorAttributions.length) { expandedImageDiv.appendChild( createAttribution(photo.authorAttributions[0]) ); } } else { expandedImageDiv.textContent = 'No photos available for this location.'; } } catch (error) { console.error('Failed to fetch place details:', error); summary.textContent = 'Failed to load data.'; } // Re-enable button after 2 seconds setTimeout(() => { randomizeBtn.disabled = false; }, 2000); } // 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; } randomizeBtn.addEventListener('click', () => void showRandomCityPhoto()); // Initial load void showRandomCityPhoto(); } void init();
CSS
/* * Optional: Makes the sample page fill the window. */ html, body { height: 100%; margin: 0; padding: 0; font-family: 'Inter', sans-serif; background: linear-gradient(135deg, #1e1e2f, #252540); display: flex; align-items: center; justify-content: center; } #container { display: flex; background: rgba(255, 255, 255, 0.05); backdrop-filter: blur(16px); -webkit-backdrop-filter: blur(16px); border: 1px solid rgba(255, 255, 255, 0.1); border-radius: 20px; padding: 30px; max-width: 900px; width: 100%; box-sizing: border-box; box-shadow: 0 25px 50px rgba(0, 0, 0, 0.3); color: white; } .place-overview { flex: 1; display: flex; flex-direction: column; justify-content: center; margin-right: 40px; } #info { position: relative; } #heading { font-size: 2.5rem; font-weight: 700; margin-top: 0; margin-bottom: 15px; background: linear-gradient(90deg, #fff, #a5b4fc); -webkit-background-clip: text; -webkit-text-fill-color: transparent; } #summary { font-size: 1.1rem; line-height: 1.6; color: #cbd5e1; } #expanded-image { position: relative; width: 400px; height: 400px; border-radius: 16px; overflow: hidden; box-shadow: 0 15px 35px rgba(0, 0, 0, 0.4); transform: perspective(1000px) rotateY(-5deg); transition: transform 0.5s ease; } #expanded-image:hover { transform: perspective(1000px) rotateY(0deg) scale(1.02); } #expanded-image img { width: 100%; height: 100%; object-fit: contain; } #randomize-btn { margin-top: 20px; padding: 12px 24px; font-size: 1.1rem; font-weight: bold; color: white; background: linear-gradient(90deg, #4f46e5, #3b82f6); border: none; border-radius: 12px; cursor: pointer; transition: transform 0.2s, background 0.3s; box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2); font-family: 'Inter', sans-serif; align-self: flex-start; } #randomize-btn:hover:not(:disabled) { transform: scale(1.05); } #randomize-btn:disabled { background: #475569; cursor: not-allowed; opacity: 0.7; } .attribution-label { position: absolute; bottom: 10px; right: 10px; background-color: rgba(0, 0, 0, 0.6); color: white; padding: 6px 12px; border-radius: 20px; font-size: 0.8rem; text-decoration: none; backdrop-filter: blur(4px); transition: background-color 0.3s; } .attribution-label:hover { background-color: rgba(0, 0, 0, 0.8); }
HTML
<html lang="en">
<head>
<title>Place Photos</title>
<link
href="https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap"
rel="stylesheet" />
<link rel="stylesheet" type="text/css" href="./style.css" />
<script type="module" src="./index.js"></script>
<script>
// prettier-ignore
(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"
});
</script>
</head>
<body>
<div id="container">
<div class="place-overview">
<div id="info">
<h1 id="heading"></h1>
<div id="summary"></div>
</div>
<button id="randomize-btn">Random City Photo</button>
</div>
<div id="expanded-image"></div>
</div>
</body>
</html>Попробуйте образец
Получите фотографии
Чтобы получить фотографии для места, включите поле photos в параметры запроса fetchFields() . Полученный экземпляр Place содержит массив, содержащий до 10 объектов Photo , из которых вы можете получить доступ к изображениям и необходимой информации об авторстве. Вызовите getURI() , чтобы вернуть URI исходной фотографии, используя PhotoOptions для установки максимальной высоты и/или ширины возвращаемого изображения. Если вы укажете значение как для maxHeight , так и для maxWidth , фотосервис изменит размер изображения до меньшего из двух размеров, сохраняя при этом исходное соотношение сторон. Если размеры не указаны, будет возвращено изображение в полном размере.
Класс Photo предоставляет следующие свойства:
-
authorAttributions: Массив объектовAuthorAttribution, содержащий необходимый текст атрибуции и URL-адреса. -
flagContentURI: Ссылка, по которой пользователь может сообщить о проблеме с фотографией. -
googleMapsURI: Ссылка для отображения фотографии на Google Maps. -
heightPx: Высота фотографии в пикселях. -
widthPx: Ширина фотографии в пикселях.
В следующем примере показано, как выполнить запрос к данным о месте для получения фотографий, вызвать getURI() для экземпляра фотографии, чтобы получить URI источника изображения, а затем добавить первую найденную фотографию в элемент img (для краткости ссылки на источники опущены):
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: ['photos'] }); // Add the first photo to an img element. const photoImg = document.getElementById('image-container'); photoImg.src = place.photos[0].getURI({maxHeight: 400});
Указание авторства
При отображении фотографии необходимо также отображать информацию об авторе. Используйте класс AuthorAttribution для возврата этой информации. Информация об авторе включает имя автора ( displayName ), URI его профиля в Google Maps ( uri ) и URI фотографии автора ( photoURI ). Следующий фрагмент кода демонстрирует возврат displayName , uri и photoURI для фотографии места.
let name = place.photos[0].authorAttributions[0].displayName; let url = place.photos[0].authorAttributions[0].uri; let authorPhoto = place.photos[0].authorAttributions[0].photoURI;