عناصر تفاصيل المكان

عنصر "تفاصيل المكان" وعنصر "تفاصيل المكان المكثّفة" هما عنصران HTML يعرضان تفاصيل مكان معيّن:

عنصر "تفاصيل المكان"

يتيح PlaceDetailsElement استخدام مجموعة كبيرة من عناصر المحتوى، بما في ذلك ساعات العمل الكاملة والموقع الإلكتروني ورقم الهاتف والخلاصة التحريرية والمعلومات البارزة الخاصة بالنوع والمراجعات والرموز البرمجية وقوائم الميزات.

لعرض تفاصيل المكان على الخريطة، أضِف عنصرًا gmp-place-details إلى عنصر gmp-map في صفحة HTML. أدرِج عنصرًا فرعيًا، gmp-place-details-place-request، لاختيار المكان. يمكن أن يكون عنصر مكان، معرّف مكان، أو اسم مورد مكان بالتنسيق "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 تفتح الصورة في إطار صور عند النقر عليها. تكون ميزة "المعرض الضوئي" غير مفعَّلة تلقائيًا.
  • يُستخدَم العنصر 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 بين 250 و400 بكسل. قد لا يتم عرض العروض التي تقلّ عن 250 بكسل بشكلٍ صحيح. اضبط الارتفاع بما يناسب تطبيقك. تم تصميم عنصر "تفاصيل المكان" بحيث يمكن التمرير للأسفل أو للأعلى ضمن المساحة المخصّصة حسب الحاجة.

يتيح عنصر gmp-place-details أيضًا مجموعة متنوعة من خصائص CSS المخصّصة لضبط ألوان العنصر وخطوطه. راجِع تصميم مخصّص لواجهة مستخدم "الأماكن" (Kit Custom Styling) للحصول على مزيد من التفاصيل.

الاطّلاع على مثال الرمز البرمجي الكامل

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، لاختيار المكان. يمكن أن يكون عنصر مكان، معرّف مكان، أو اسم مورد مكان بالتنسيق "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 في الاتجاه العمودي هو من 180 بكسل إلى 300 بكسل. قد لا يتم عرض العروض التي تقل عن 160 بكسل بشكل صحيح. لا تضبط ارتفاعًا ثابتًا.

يتراوح العرض المقترَح للعنصر gmp-place-details-compact في الوضع الأفقي بين 180 و500 بكسل. قد لا يتم عرض العروض التي تقل عن 160 بكسل بشكل صحيح. عند عرض الصور بعرض أقل من 350 بكسل، لن يتم عرض الصورة المصغّرة. لا تضبط ارتفاعًا ثابتًا.

يتيح عنصر gmp-place-details-compact أيضًا مجموعة متنوعة من خصائص CSS المخصّصة لضبط ألوان العنصر وخطوطه. راجِع تصميم مخصّص لواجهة مستخدم "الأماكن" (Kit Custom Styling) للحصول على مزيد من التفاصيل.

الاطّلاع على مثال الرمز البرمجي الكامل

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>