רכיבים של פרטי המקום

רכיב פרטי המקום ורכיב פרטי המקום הקומפקטי הם רכיבי HTML שמציגים את הפרטים של מקום מסוים:

רכיב פרטי המקום

התג PlaceDetailsElement תומך במגוון רחב של רכיבי תוכן, כולל שעות פתיחה מלאות, אתר, מספר טלפון, סיכום עריכה, נתונים ספציפיים לסוג העסק, ביקורות, קוד Plus ורשימה של תכונות.

כדי להציג את פרטי המקום במפה, מוסיפים רכיב gmp-place-details לרכיב gmp-map בדף ה-HTML. כדי לבחור את המקום, צריך לכלול רכיב צאצא, gmp-place-details-place-request. זה יכול להיות אובייקט Place, מזהה מקום או שם המשאב של מקום בפורמט 'places/{place_id}':

<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-details באמצעות רכיב gmp-place-content-config בתצוגת עץ, כדי לבחור את פרטי המקום ולהגדיר אותם, כפי שמתואר בדוגמה הבאה:

<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-color ו-dark-scheme-color משמשים להגדרת הצבע של טקסט השיוך במצב בהיר ובמצב כהה.
למידע נוסף על כל רכיבי התוכן הנתמכים, אפשר לעיין במסמכי העזרה של PlaceContentConfigElement.

כדי לפשט את התהליך, אפשר להחליף את הרכיב gmp-place-content-config ברכיב gmp-place-all-content כדי להציג את כל הפרטים שזמינים ברכיב 'פרטי המקום', או ברכיב gmp-place-standard-content כדי להציג הגדרה רגילה.

הגדרת המראה

טווח הרוחב המומלץ לרכיב gmp-place-details הוא 250px עד 400px. יכול להיות שתמונות ברוחב קטן מ-250px לא יוצגו בצורה תקינה. מגדירים את הגובה בהתאם לאפליקציה. הרכיב 'פרטי המקום' תוכנן לגלילה בתוך המרחב שהוקצה לו לפי הצורך.

האלמנט gmp-place-details תומך גם במגוון מאפייני CSS בהתאמה אישית כדי להגדיר את הצבעים והגופנים של האלמנט. למידע נוסף, ראו עיצוב מותאם אישית של ערכת ממשק המשתמש של Places.

הצגת דוגמת הקוד המלאה

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: 400px;
}

gmp-place-details {
  border-radius: 0px;
  margin: 20px;
  width: 400px;
  height: 400px;
  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>

רכיב קומפקטי של פרטי המקום

האפשרות PlaceDetailsCompactElement מציגה פרטים על מקום שנבחר בשטח מינימלי. האפשרות הזו שימושית בחלון מידע שמציג מקום במפה, בחוויית שימוש ברשתות חברתיות כמו שיתוף מיקום בצ'אט, כהצעה לבחירת המיקום הנוכחי או במאמר במדיה כדי להפנות למקום במפות Google.ב-PlaceDetailsCompactElement אפשר להציג את השם, הכתובת, הדירוג, הסוג, המחיר, סמל הנגישות, סטטוס הפתיחה ותמונה אחת.

כדי להוסיף את הרכיב למפה, מוסיפים רכיב gmp-place-details-compact לרכיב gmp-map בדף ה-HTML, ומשתמשים במאפיין orientation כדי לבחור אם הוא יוצג אופקית או אנכית.

בדוגמה הבאה, gmp-place-details-compact מוטמע בתוך אלמנט gmp-map, כאשר הערך של orientation מוגדר ל-horizontal. מאפיין נוסף, truncation-preferred, מקצר תוכן מסוים כדי שיתאימו לשורה אחת במקום להסתובב. הרכיב gmp-place-details-compact מכיל רכיב בן, gmp-place-details-place-request, כדי לבחור את המקום. זה יכול להיות אובייקט Place, מזהה מקום או שם המשאב של מקום בפורמט 'places/{place_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-details-compact באמצעות רכיב gmp-place-content-config בתצוגת עץ, כדי לבחור את פרטי המקום ולהגדיר אותם. רכיב gmp-place-content-config עצמו מכיל מספר רכיבי תוכן צאצאים, וכל אחד מהם בוחר פרט מקום תואם להצגה. הסדר של רכיבי הצאצאים לא רלוונטי, כי הפרטים שנבחרו תמיד מוצגים בסדר קבוע מוגדר מראש. אפשר להגדיר חלק מהרכיבים האלה באופן נוסף באמצעות מאפיינים ספציפיים לתוכן.

מידע נוסף על כל רכיבי התוכן הנתמכים זמין במסמכי העזרה של PlaceContentConfigElement.

כדי לפשט את התהליך, אפשר להחליף את האלמנט gmp-place-content-config באלמנט gmp-place-all-content כדי להציג את כל הפרטים שזמינים באלמנט 'פרטי המקום בפורמט קומפקטי', או באלמנט gmp-place-standard-content כדי להציג הגדרה רגילה.

הגדרת המראה

טווח הרוחב המומלץ לרכיב gmp-place-details-compact בכיוון אנכי הוא 180px-300px. יכול להיות שתמונות ברוחב של פחות מ-160px לא יוצגו כמו שצריך. אין להגדיר גובה קבוע.

הטווח המומלץ לרוחב של הרכיב gmp-place-details-compact בכיוון אופקי הוא 180px-500px. יכול להיות שתמונות ברוחב של פחות מ-160px לא יוצגו כמו שצריך. בתמונות ברוחב קטן מ-350 פיקסלים, התמונה הממוזערת לא תוצג. אין להגדיר גובה קבוע.

האלמנט gmp-place-details-compact תומך גם במגוון מאפייני CSS בהתאמה אישית כדי להגדיר את הצבעים והגופנים של האלמנט. למידע נוסף, אפשר לעיין במאמר עיצוב מותאם אישית של ערכת ממשק המשתמש של Places.

הצגת דוגמת הקוד המלאה

JavaScript

// Use querySelector to select elements for interaction.
const mapContainer = document.getElementById("map-container");
const detailsContainer = document.getElementById("details-container");
const placeDetails = document.querySelector("gmp-place-details-compact");
const placeDetailsRequest = document.querySelector("gmp-place-details-place-request");
let gMap;
let infowindow;
let marker;
async function initMap() {
    const { PlaceDetailsCompactElement, PlaceDetailsPlaceRequestElement } = await google.maps.importLibrary("places");
    const { Map, InfoWindow } = 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 });
    infowindow = new InfoWindow({});
    // 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) => {
        marker.position = null;
        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) {
            gMap.panTo(placeDetails.place.location);
            gMap.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';
            //@ts-ignore
            infowindow.setOptions({
                content: placeDetails
            });
            //@ts-ignore
            infowindow.open({
                anchor: marker,
                map: gMap,
            });
        }
    };
}
initMap();

CSS

html,
body {
  display: flex;
  width: 100%;
  height: 100%;
  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;
  overflow-y: hidden;
}

.gm-style-iw button {
    display: none !important;
}

.gm-style-iw-c {
    padding: 0 !important;
    margin: 0 !important;
}

.gm-style-iw-d {
    padding: 0 !important;
    margin: 0 !important; /* Sometimes margin can also contribute to unwanted space */
    overflow: visible !important; /* If you don't want scrollbars, but be careful with content overflow */
}

.gm-style-iw-c * { /* Target all elements inside the infowindow content container */
    padding: 0 !important;
    margin: 0 !important;
}

@media (prefers-color-scheme: dark) {

    .gm-style-iw.gm-style-iw-c,
    .gm-style .gm-style-iw-d,
    .gm-style .gm-style-iw-d::-webkit-scrollbar-track, 
    .gm-style .gm-style-iw-d::-webkit-scrollbar-track-piece,
    .gm-style .gm-style-iw-c,
    .gm-style .gm-style-iw-t::after,
    .gm-style .gm-style-iw-tc::after { 
        background-color: #000 !important;
    }
    .gm-ui-hover-effect>span {
        background-color: #fff !important;
    }
}

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">
        <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>
    </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>