PlaceDetails 元素

選取平台: Android iOS JavaScript

Place Details 元素和 Place Details Compact 元素是 HTML 元素,可顯示地點的詳細資料:

  • PlaceDetailsElement 支援所有可視化的地點資料,且可能包含多張相片。
  • PlaceDetailsCompactElement 旨在盡量節省空間,並顯示地點的簡要資訊,包括名稱、地址、評分等。也可能包含單張相片。

Place Details 元素

按一下地圖上的標記,即可在「地點詳細資料」元素中查看地點詳細資料。

PlaceDetailsElement 支援各種內容元素,包括完整營業時間、網站、電話號碼、編輯摘要、特定類型重點、評論、加號代碼和功能清單。

如要在地圖上顯示地點詳細資料,請在 HTML 網頁的 gmp-map 元素中新增 gmp-place-details 元素。加入子項元素 gmp-place-details-place-request 來選取地點。可以是地點物件地點 ID 或地點的資源名稱:

<gmp-map center="47.759737, -122.250632" zoom="16" map-id="DEMO_MAP_ID">
    <gmp-advanced-marker></gmp-advanced-marker>
</gmp-map>
<gmp-map center="47.759737, -122.250632" zoom="16" map-id="DEMO_MAP_ID">
  <div class="widget-container" slot="control-inline-start-block-start">
    <gmp-place-details>
      <gmp-place-details-place-request place="ChIJC8HakaIRkFQRiOgkgdHmqkk"></gmp-place-details-place-request>
      <gmp-place-all-content></gmp-place-all-content>
    </gmp-place-details>
  </div>
  <gmp-advanced-marker></gmp-advanced-marker>
</gmp-map>

設定內容

您可以使用巢狀 gmp-place-content-config 元素選取及設定地點詳細資料,藉此控管 gmp-place-details 元素顯示的特定地點內容,如以下範例所示:

<gmp-map center="47.759737, -122.250632" zoom="16" map-id="DEMO_MAP_ID">
  <div class="widget-container" slot="control-inline-start-block-start">
    <gmp-place-details>
      <gmp-place-details-place-request place="ChIJC8HakaIRkFQRiOgkgdHmqkk"></gmp-place-details-place-request>
      <gmp-place-content-config>
        <gmp-place-address></gmp-place-address>
        <gmp-place-rating></gmp-place-rating>
        <gmp-place-type></gmp-place-type>
        <gmp-place-price></gmp-place-price>
        <gmp-place-accessible-entrance-icon></gmp-place-accessible-entrance-icon>
        <gmp-place-opening-hours></gmp-place-opening-hours>
        <gmp-place-website></gmp-place-website>
        <gmp-place-phone-number></gmp-place-phone-number>
        <gmp-place-summary></gmp-place-summary>
        <gmp-place-type-specific-highlights></gmp-place-type-specific-highlights>
        <gmp-place-reviews></gmp-place-reviews>
        <gmp-place-feature-list></gmp-place-feature-list>
        <gmp-place-media lightbox-preferred></gmp-place-media>
        <gmp-place-attribution light-scheme-color="gray" dark-scheme-color="white"></gmp-place-attribution>
      </gmp-place-content-config>
    </gmp-place-details>
  </div>
  <gmp-advanced-marker></gmp-advanced-marker>
</gmp-map>

gmp-place-content-config 元素本身包含許多子項內容元素,每個元素都會選取要顯示的相應地點詳細資料:PlaceAddressElement 會選取地點的地址,PlacePriceElement 會選取地點的價格等級等。子項元素的順序無關緊要,因為所選詳細資料一律會以預先定義的固定順序呈現。

您可以使用內容專屬屬性,進一步設定這些元素:

  • gmp-place-media 元素用於顯示單一相片,並包含 lightbox-preferred 屬性,點選後會在燈箱中開啟相片。 Lightbox 預設為停用。
  • gmp-place-attribution 元素用於顯示相片來源。light-scheme-colordark-scheme-color 屬性用於在淺色和深色模式中設定出處文字的顏色。
如要進一步瞭解所有支援的內容元素,請參閱 PlaceContentConfigElement 參考說明文件。

為求簡化, gmp-place-content-config 元素可以取代為 gmp-place-all-content,顯示 Place Details 元素中的所有詳細資料,也可以取代為 gmp-place-standard-content,顯示標準設定。

設定外觀

建議 gmp-place-details 元素的寬度範圍為 250 像素到 400 像素。 寬度小於 250 像素時,可能無法正確顯示。設定適合應用程式的高度。 Place Details 元素的設計可視需要捲動所分配的空間。

gmp-place-details 元素也支援多種自訂 CSS 屬性,可設定元素的顏色和字型。詳情請參閱「Places UI Kit 自訂樣式」。

查看完整程式碼範例

JavaScript

// Use querySelector to select elements for interaction.
const map = document.querySelector('gmp-map');
const placeDetails = document.querySelector('gmp-place-details');
const placeDetailsRequest = document.querySelector('gmp-place-details-place-request');
const marker = document.querySelector('gmp-advanced-marker');
let center = { lat: 47.759737, lng: -122.250632 };
async function initMap() {
    // Request needed libraries.
    (await google.maps.importLibrary('maps'));
    (await google.maps.importLibrary('marker'));
    (await google.maps.importLibrary('places'));
    // Hide the map type control.
    map.innerMap.setOptions({ mapTypeControl: false });
    // Function to update map and marker based on place details
    const updateMapAndMarker = () => {
        if (placeDetails.place && placeDetails.place.location) {
            let adjustedCenter = offsetLatLngRight(placeDetails.place.location, -0.005);
            map.innerMap.panTo(adjustedCenter);
            map.innerMap.setZoom(16); // Set zoom after panning if needed
            marker.position = placeDetails.place.location;
            marker.collisionBehavior =
                google.maps.CollisionBehavior.REQUIRED_AND_HIDES_OPTIONAL;
            marker.style.display = 'block';
        }
    };
    // Set up map once widget is loaded.
    placeDetails.addEventListener('gmp-load', (event) => {
        updateMapAndMarker();
    });
    // Add an event listener to handle clicks.
    map.innerMap.addListener('click', async (event) => {
        marker.position = null;
        event.stop();
        if (event.placeId) {
            // Fire when the user clicks a POI.
            placeDetailsRequest.place = event.placeId;
            updateMapAndMarker();
        }
        else {
            // Fire when the user clicks the map (not on a POI).
            console.log('No place was selected.');
            marker.style.display = 'none';
        }
    });
}
// Helper function to offset marker placement for better visual appearance.
function offsetLatLngRight(latLng, longitudeOffset) {
    const newLng = latLng.lng() + longitudeOffset;
    return new google.maps.LatLng(latLng.lat(), newLng);
}
initMap();

CSS

/* 
 * Optional: Makes the sample page fill the window. 
 */
html,
body {
    display: flex; /* Use flexbox for layout */
    justify-content: center; /* Center the content horizontally */
    align-items: flex-start; /* Align items to the top */
    width: 100%;
}

h1 {
    font-size: 16px;
    text-align: center;
}

gmp-map {
    height: 500px;
}

gmp-place-details {
    border-radius: 0px;
    margin: 20px;
    width: 400px;
    height: 500px;
    margin-top: 0px;
}

gmp-advanced-marker {
    display: none;
}

.widget-container {
    min-width: 400px;
    overflow-y: none;
    overflow-x: none;
}

HTML

<!doctype html>
<html>
    <head>
        <title>Click on the map to view place details</title>
        <meta charset="utf-8" />
        <link rel="stylesheet" href="style.css" />
        <script type="module" src="./index.js"></script>
    </head>
    <body>
        <gmp-map center="47.759737, -122.250632" zoom="16" map-id="DEMO_MAP_ID">
            <gmp-advanced-marker></gmp-advanced-marker>
        </gmp-map>
        <div class="widget-container" slot="control-inline-start-block-start">
            <gmp-place-details>
                <gmp-place-details-place-request
                    place="ChIJC8HakaIRkFQRiOgkgdHmqkk"></gmp-place-details-place-request>
                <gmp-place-all-content></gmp-place-all-content>
            </gmp-place-details>
        </div>
        <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>
    </body>
</html>

Place Details Compact 元素

按一下地圖上的標記,即可在「地點詳細資料精簡元素」中查看地點詳細資料。

PlaceDetailsCompactElement 會使用最少的空間,顯示所選地點的詳細資料。這項功能可能適用於資訊視窗 (醒目顯示地圖上的地點)、社群媒體體驗 (例如在即時通訊中分享位置)、選取目前位置的建議,或媒體文章 (參照 Google 地圖上的地點)。PlaceDetailsCompactElement 可顯示名稱、地址、評分、類型、價格、無障礙圖示、營業狀態和單張相片。可以水平或垂直顯示,視 orientation 屬性而定。

在以下程式碼片段中,gmp-place-details-compact 會巢狀內嵌在 gmp-map 元素內,且 orientation 設為 horizontal。另一個屬性 truncation-preferred 會截斷特定內容,以便在單行顯示所有內容,而不是換行。gmp-place-details-compact 元素包含子元素 gmp-place-details-place-request,可選取地點。可以是地點物件地點 ID 或地點的資源名稱。

<gmp-map center="47.75972, -122.25094" zoom="19" map-id="DEMO_MAP_ID">
  <gmp-place-details-compact orientation = "horizontal" truncation-preferred slot="control-block-start-inline-center" >
    <gmp-place-details-place-request place = "ChIJC8HakaIRkFQRiOgkgdHmqkk"></gmp-place-details-place-request>
    <gmp-place-content-config>
        <gmp-place-media lightbox-preferred></gmp-place-media>
        <gmp-place-rating></gmp-place-rating>
        <gmp-place-type></gmp-place-type>
        <gmp-place-price></gmp-place-price>
        <gmp-place-accessible-entrance-icon></gmp-place-accessible-entrance-icon>
        <gmp-place-open-now-status></gmp-place-open-now-status>
        <gmp-place-attribution light-scheme-color="gray" dark-scheme-color="white"></gmp-place-attribution>
    </gmp-place-content-config>
  </gmp-place-details-compact>
  <gmp-advanced-marker></gmp-advanced-marker>
</gmp-map>

設定內容

您可以使用巢狀 gmp-place-content-config 元素選取及設定地點詳細資料,藉此控管 gmp-place-details-compact 元素顯示的特定地點內容。gmp-place-content-config 元素本身包含多個子項內容元素,每個元素都會選取要顯示的相應地點詳細資料。子項元素的順序無關緊要,因為所選詳細資料一律會以預先定義的固定順序呈現。部分元素可使用內容專屬屬性進一步設定。

如要進一步瞭解所有支援的內容元素,請參閱PlaceContentConfigElement參考說明文件。

為簡化作業, gmp-place-content-config 元素可以取代為 gmp-place-all-content,顯示地點詳細資料精簡元素中的所有詳細資料,也可以取代為 gmp-place-standard-content,顯示標準設定。

設定外觀

直向模式下,gmp-place-details-compact 元素的建議寬度範圍為 180 像素至 300 像素。寬度小於 160 像素時,可能無法正確顯示。請勿設定固定高度。

在橫向模式中,gmp-place-details-compact 元素的建議寬度範圍為 180 像素到 500 像素。寬度小於 160 像素時,可能無法正確顯示。如果寬度小於 350 像素,系統就不會顯示縮圖。請勿設定固定高度。

gmp-place-details-compact 元素也支援多種自訂 CSS 屬性,可設定元素的顏色和字型。詳情請參閱「Places UI Kit 自訂樣式」。

查看完整程式碼範例

這個範例示範如何使用 AdvancedMarkerElement,以程式輔助方式將 PlaceDetailsCompactElement 新增至地圖。

JavaScript

// Use querySelector to select elements for interaction.
const mapContainer = document.getElementById('map-container');
const placeDetails = document.querySelector('gmp-place-details-compact');
const placeDetailsRequest = document.querySelector('gmp-place-details-place-request');
let gMap;
let marker;
async function initMap() {
    const { PlaceDetailsCompactElement, PlaceDetailsPlaceRequestElement } = (await google.maps.importLibrary('places'));
    const { Map } = (await google.maps.importLibrary('maps'));
    const { AdvancedMarkerElement } = (await google.maps.importLibrary('marker'));
    gMap = new Map(mapContainer, { mapId: 'DEMO_MAP_ID' });
    marker = new AdvancedMarkerElement({ map: gMap });
    // Hide the map type control.
    gMap.setOptions({ mapTypeControl: false });
    // Set up map, marker, and infowindow once widget is loaded.
    placeDetails.style.visibility = 'visible';
    placeDetails.addEventListener('gmp-load', (event) => {
        console.log('placeDetails initialized!');
        updateMapAndMarker();
    });
    // Add an event listener to handle clicks.
    gMap.addListener('click', async (event) => {
        event.stop();
        // Fire when the user clicks on a POI.
        if (event.placeId) {
            console.log('clicked on POI');
            console.log(event.placeId);
            placeDetailsRequest.place = event.placeId;
            updateMapAndMarker();
        }
        else {
            // Fire when the user clicks the map (not on a POI).
            console.log('No place was selected.');
        }
    });
    // Function to update map, marker, and infowindow based on place details
    const updateMapAndMarker = () => {
        console.log('function called');
        if (placeDetails.place && placeDetails.place.location) {
            marker.gMap = null;
            let adjustedCenter = offsetLatLngRight(placeDetails.place.location, 0.002);
            gMap.panTo(adjustedCenter);
            gMap.setZoom(16); // Set zoom after panning if needed
            marker.content = placeDetails;
            marker.position = placeDetails.place.location;
        }
        else {
            console.log('else');
        }
    };
}
// Helper function to offset marker placement for better visual appearance.
function offsetLatLngRight(latLng, latitudeOffset) {
    const newLat = latLng.lat() + latitudeOffset;
    return new google.maps.LatLng(newLat, latLng.lng());
}
initMap();

CSS

html,
body {
    display: flex;
    width: 100%;
    height: 400px;
    margin: 0;
}

h1 {
    font-size: 16px;
    text-align: center;
}

#map-container {
    box-sizing: border-box;
    width: 100%;
}
gmp-place-details-compact {
    /* Sets the color for text and icons on the surface */
    /* Adapts automatically to the user's system light/dark mode preference */
    --gmp-mat-color-on-surface: light-dark(black, white);
    /* Sets the background color of the surface */
    /* Adapts automatically to the user's system light/dark mode preference */
    --gmp-mat-color-surface: light-dark(white, black);
    /* Defines the primary font stack used within the component */
    --gmp-mat-font-family: Google Sans Text, sans-serif;
    /* Defines the style for medium body text (e.g., address, descriptions) */
    --gmp-mat-font-body-medium: normal 400 0.875em/1.25em
        var(--gmp-mat-font-family, 'Google Sans Text');

    width: 360px;
    border: none;
    padding: 0;
    margin: 0;
    position: relative;
    transform: translate(0, calc(-20px));
}

/* This creates the pointer attached to the bottom of the element. */
gmp-place-details-compact::after {
    content: '';
    position: absolute;
    top: 100%;
    left: 50%;
    transform: translateX(-50%);
    width: 0;
    height: 0;
    border-left: 16px solid transparent;
    border-right: 16px solid transparent;
    border-top: 20px solid
        var(--gmp-mat-color-surface, light-dark(white, black));
}

HTML

<!doctype html>
<html>
    <head>
        <title>Click on the map to view place details</title>
        <meta charset="utf-8" />
        <link rel="stylesheet" href="style.css" />
        <script type="module" src="./index.js"></script>
    </head>
    <body>
        <div id="map-container"></div>
        <gmp-place-details-compact orientation="horizontal">
            <gmp-place-details-place-request
                place="ChIJn97JQNpC1moRIcJsVMEQLI8"></gmp-place-details-place-request>
            <gmp-place-all-content></gmp-place-all-content>
        </gmp-place-details-compact>
        <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>
    </body>
</html>