Place Photos

Sviluppatori dello Spazio economico europeo (SEE)

Place Photos ti consente di aggiungere contenuti fotografici di alta qualità alle tue pagine web. Accedi a milioni di foto archiviate nel database di Places e ottieni immagini ridimensionabili utilizzando Trova luogo, Ricerca nelle vicinanze, Ricerca di testo, Completamento automatico e Places Details.

Visualizza il codice sorgente dell'esempio completo

Questo carosello di foto rudimentale mostra le foto del luogo specificato, incluse le attribuzioni dell'autore richieste (visualizzate nell'angolo in alto a sinistra della foto selezionata).

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>

Prova campione

Scarica le foto

Per ottenere le foto di un luogo, includi il campo photos nei parametri della richiesta fetchFields(). L'istanza di Place risultante contiene un array di fino a 10 oggetti Photo, da cui puoi accedere alle immagini e alle informazioni di attribuzione richieste. Chiama getURI() per restituire l'URI della foto di origine, utilizzando PhotoOptions per impostare l'altezza e/o la larghezza massime dell'immagine restituita. Se specifichi un valore sia per maxHeight sia per maxWidth, il servizio fotografico ridimensionerà l'immagine in base alla più piccola delle due dimensioni, mantenendo le proporzioni originali. Se non viene specificata alcuna dimensione, verrà restituita l'immagine a grandezza naturale.

La classe Photo espone le seguenti proprietà:

  • authorAttributions: un array di oggetti AuthorAttribution contenenti il testo e gli URL di attribuzione richiesti.
  • flagContentURI: un link in cui l'utente può segnalare un problema con la foto.
  • googleMapsURI: un link per mostrare la foto su Google Maps.
  • heightPx: l'altezza della foto in pixel.
  • widthPx: la larghezza della foto in pixel.

L'esempio seguente mostra come effettuare una richiesta Place Details per le foto, chiamando getURI() su un'istanza di foto per restituire l'URI di origine dell'immagine, quindi aggiungendo il primo risultato della foto a un elemento img (le attribuzioni sono omesse per brevità):

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});

Attribuzioni degli autori

Quando visualizzi una foto, devi mostrare anche le attribuzioni dell'autore. Utilizza la classe AuthorAttribution per restituire le attribuzioni. Un'attribuzione include il nome dell'autore (displayName), un URI per il suo profilo Google Maps (uri) e un URI per la sua foto (photoURI). Il seguente snippet mostra la restituzione di displayName, uri e photoURI per una foto del luogo.

  let name = place.photos[0].authorAttributions[0].displayName;
  let url = place.photos[0].authorAttributions[0].uri;
  let authorPhoto = place.photos[0].authorAttributions[0].photoURI;