تتطلّب خدمة "البحث في الجوار (جديد)" نوع مكان واحدًا أو أكثر، وتعرض قائمة بالأماكن المطابقة. في المثال التالي، يمكنك اختيار نوع مكان والاطّلاع على النتائج على خريطة. انقر على العلامات للاطّلاع على مزيد من التفاصيل حول الأماكن.
تعرض خدمة بحث في الجوار (جديد) معلومات عن مجموعة من الأماكن استنادًا إلى أنواع الأماكن التي تحدّدها، مثل restaurant أو book_store أو bowling_alley. تستجيب الخدمة بقائمة من الأماكن التي تطابق أنواع الأماكن المحدّدة ضمن نطاق locationRestriction المحدّد.
لاستخدام ميزة "البحث في الجوار (الجديدة)"، يجب تفعيل "Places API (الجديدة)" في مشروعك على Google Cloud. لمزيد من التفاصيل، يُرجى الاطّلاع على البدء.
العثور على الأماكن المجاورة
استخدِم الدالة searchNearby()
لعرض قائمة بالأماكن استنادًا إلى أنواع الأماكن والموقع الجغرافي والنطاق الجغرافي المحدّدة. حدِّد مَعلمات البحث باستخدام طلب، ثم استدعِ searchNearby(). يتم عرض النتائج
كقائمة من عناصر Place، والتي يمكنك من خلالها الحصول على
تفاصيل المكان.
يعرض المقتطف التالي مثالاً على طلب واستدعاء لـ searchNearby():
TypeScript
// Get bounds and radius to constrain search. center = mapElement.center!; const ne = innerMap.getBounds()!.getNorthEast(); const sw = innerMap.getBounds()!.getSouthWest(); const diameter = spherical.computeDistanceBetween(ne, sw); const radius = Math.min(diameter / 2, 50000); // Radius cannot be more than 50000. const request = { // required parameters fields: [ 'displayName', 'location', 'formattedAddress', 'googleMapsURI', ], locationRestriction: { center, radius, }, // optional parameters includedPrimaryTypes: [typeSelect.value], maxResultCount: 5, rankPreference: SearchNearbyRankPreference.POPULARITY, }; const { places } = await Place.searchNearby(request);
JavaScript
// Get bounds and radius to constrain search. center = mapElement.center; const ne = innerMap.getBounds().getNorthEast(); const sw = innerMap.getBounds().getSouthWest(); const diameter = spherical.computeDistanceBetween(ne, sw); const radius = Math.min(diameter / 2, 50000); // Radius cannot be more than 50000. const request = { // required parameters fields: [ 'displayName', 'location', 'formattedAddress', 'googleMapsURI', ], locationRestriction: { center, radius, }, // optional parameters includedPrimaryTypes: [typeSelect.value], maxResultCount: 5, rankPreference: SearchNearbyRankPreference.POPULARITY, }; const { places } = await Place.searchNearby(request);
- استخدِم المَعلمة
fields(مطلوبة) لتحديد قائمة قيم مفصولة بفاصلة تتضمّن حقل بيانات واحدًا أو أكثر. تحدّد الحقول التي تطلبها سعر الطلب. يُرجى الاطّلاع على اختيار حقول البيانات. - استخدِم مَعلمة
locationRestriction(مطلوبة) لتحديد نطاق يصل إلى 50,000 متر. - استخدِم المَعلمة
includedPrimaryTypesلتحديد نوع مكان واحد أو أكثر للبحث عنه. - استخدِم المَعلمة
rankPreferenceلتحديدSearchNearbyRankPreferenceإماPOPULARITYأوDISTANCE. - الاطّلاع على القائمة الكاملة للمَعلمات
مثال
يستخدم المثال التالي searchNearby() لطلب البحث عن أماكن من النوع المحدّد ضمن حدود الخريطة، ويملأ خريطة بعلامات لعرض النتائج.
TypeScript
const mapElement = document.querySelector('gmp-map')!; let innerMap: google.maps.Map; let center: google.maps.LatLngLiteral | google.maps.LatLng; let typeSelect: HTMLSelectElement; let infoWindow: google.maps.InfoWindow; async function init() { const [{ InfoWindow }, { event }] = await Promise.all([ google.maps.importLibrary('maps'), google.maps.importLibrary('core'), ]); innerMap = mapElement.innerMap; innerMap.setOptions({ mapTypeControl: false, }); typeSelect = document.querySelector('.type-select')!; typeSelect.addEventListener('change', () => { void nearbySearch(); }); infoWindow = new InfoWindow(); // Kick off an initial search once map has loaded. event.addListenerOnce(innerMap, 'idle', () => { void nearbySearch(); }); } async function nearbySearch() { const [ { Place, SearchNearbyRankPreference }, { AdvancedMarkerElement }, { spherical }, ] = await Promise.all([ google.maps.importLibrary('places'), google.maps.importLibrary('marker'), google.maps.importLibrary('geometry'), ]); // Get bounds and radius to constrain search. center = mapElement.center!; const ne = innerMap.getBounds()!.getNorthEast(); const sw = innerMap.getBounds()!.getSouthWest(); const diameter = spherical.computeDistanceBetween(ne, sw); const radius = Math.min(diameter / 2, 50000); // Radius cannot be more than 50000. const request = { // required parameters fields: [ 'displayName', 'location', 'formattedAddress', 'googleMapsURI', ], locationRestriction: { center, radius, }, // optional parameters includedPrimaryTypes: [typeSelect.value], maxResultCount: 5, rankPreference: SearchNearbyRankPreference.POPULARITY, }; const { places } = await Place.searchNearby(request); if (places.length) { const { LatLngBounds } = await google.maps.importLibrary('core'); const bounds = new LatLngBounds(); // First remove all existing markers. for (const marker of mapElement.querySelectorAll('gmp-advanced-marker')) marker.remove(); // Loop through and get all the results. places.forEach((place) => { if (!place.location) return; bounds.extend(place.location); const marker = new AdvancedMarkerElement({ map: innerMap, position: place.location, title: place.displayName, gmpClickable: true, }); // Build the content of the InfoWindow safely using DOM elements. const content = document.createElement('div'); const address = document.createElement('div'); address.textContent = place.formattedAddress || ''; const placeId = document.createElement('div'); placeId.textContent = place.id; content.append(address, placeId); if (place.googleMapsURI) { const link = document.createElement('a'); link.href = place.googleMapsURI; link.target = '_blank'; link.textContent = 'View Details on Google Maps'; content.appendChild(link); } marker.addEventListener('gmp-click', () => { innerMap.panTo(place.location!); updateInfoWindow(place.displayName!, content, marker); }); }); innerMap.fitBounds(bounds, 100); } else { console.log('No results'); } } function updateInfoWindow( title: string | Element | null, content: string | Element | null, anchor: google.maps.marker.AdvancedMarkerElement ) { infoWindow.setContent(content); infoWindow.setHeaderContent(title); infoWindow.open({ anchor, }); } void init();
JavaScript
const mapElement = document.querySelector('gmp-map'); let innerMap; let center; let typeSelect; let infoWindow; async function init() { const [{ InfoWindow }, { event }] = await Promise.all([ google.maps.importLibrary('maps'), google.maps.importLibrary('core'), ]); innerMap = mapElement.innerMap; innerMap.setOptions({ mapTypeControl: false, }); typeSelect = document.querySelector('.type-select'); typeSelect.addEventListener('change', () => { void nearbySearch(); }); infoWindow = new InfoWindow(); // Kick off an initial search once map has loaded. event.addListenerOnce(innerMap, 'idle', () => { void nearbySearch(); }); } async function nearbySearch() { const [ { Place, SearchNearbyRankPreference }, { AdvancedMarkerElement }, { spherical }, ] = await Promise.all([ google.maps.importLibrary('places'), google.maps.importLibrary('marker'), google.maps.importLibrary('geometry'), ]); // Get bounds and radius to constrain search. center = mapElement.center; const ne = innerMap.getBounds().getNorthEast(); const sw = innerMap.getBounds().getSouthWest(); const diameter = spherical.computeDistanceBetween(ne, sw); const radius = Math.min(diameter / 2, 50000); // Radius cannot be more than 50000. const request = { // required parameters fields: [ 'displayName', 'location', 'formattedAddress', 'googleMapsURI', ], locationRestriction: { center, radius, }, // optional parameters includedPrimaryTypes: [typeSelect.value], maxResultCount: 5, rankPreference: SearchNearbyRankPreference.POPULARITY, }; const { places } = await Place.searchNearby(request); if (places.length) { const { LatLngBounds } = await google.maps.importLibrary('core'); const bounds = new LatLngBounds(); // First remove all existing markers. for (const marker of mapElement.querySelectorAll('gmp-advanced-marker')) marker.remove(); // Loop through and get all the results. places.forEach((place) => { if (!place.location) return; bounds.extend(place.location); const marker = new AdvancedMarkerElement({ map: innerMap, position: place.location, title: place.displayName, gmpClickable: true, }); // Build the content of the InfoWindow safely using DOM elements. const content = document.createElement('div'); const address = document.createElement('div'); address.textContent = place.formattedAddress || ''; const placeId = document.createElement('div'); placeId.textContent = place.id; content.append(address, placeId); if (place.googleMapsURI) { const link = document.createElement('a'); link.href = place.googleMapsURI; link.target = '_blank'; link.textContent = 'View Details on Google Maps'; content.appendChild(link); } marker.addEventListener('gmp-click', () => { innerMap.panTo(place.location); updateInfoWindow(place.displayName, content, marker); }); }); innerMap.fitBounds(bounds, 100); } else { console.log('No results'); } } function updateInfoWindow(title, content, anchor) { infoWindow.setContent(content); infoWindow.setHeaderContent(title); infoWindow.open({ anchor, }); } void init();
CSS
/* * Always set the map height explicitly to define the size of the div element * that contains the map. */ gmp-map { height: 100%; } #map-container { display: flex; flex-direction: row; height: 100%; } /* * Optional: Makes the sample page fill the window. */ html, body { height: 100%; margin: 0; padding: 0; } .type-select { width: 400px; height: 32px; border: 1px solid #000; border-radius: 10px; flex-grow: 1; padding: 0 10px; margin-left: 10px; margin-top: 10px; }
HTML
<html>
<head>
<title>Nearby Search</title>
<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: "GOOGLE_MAPS_API_KEY"
});
</script>
</head>
<body>
<gmp-map center="45.438646,12.327573" zoom="14" map-id="DEMO_MAP_ID"
><!-- Map id is required for Advanced Markers. -->
<gmp-advanced-marker></gmp-advanced-marker>
<div id="controls" slot="control-inline-start-block-start">
<select name="types" class="type-select">
<option value="cafe" selected>Cafe</option>
<option value="restaurant">Restaurant</option>
<option value="museum">Museum</option>
<option value="monument">Monument</option>
<option value="park">Park</option>
</select>
</div>
</gmp-map>
</body>
</html>اختيار حقول البيانات
تحدّد الحقول التي تطلبها سعر كل طلب بحث. يتم تحصيل رسوم الطلب
مرة واحدة، وفقًا
لأعلى
رمز تخزين تعريفي بين الحقول المطلوبة. على سبيل المثال، عند إضافة
reviews
إلى
fields،
تتم فوترة الطلب بالكامل على أنّه بحث في الجوار رزمة الشركات + Atmosphere.
لإبقاء طلبات بحث في الجوار في Nearby Search Pro، اطلب فقط الحقول التي تعرضها نتائج البحث، مثل id وdisplayName وformattedAddress وlocation.
عندما يختار مستخدم مكانًا، يمكنك استدعاء
fetchFields()
في ذلك المكان للحصول على حقول مثل
reviews
أو
nationalPhoneNumber
أو
websiteURI.
كل طلب fetchFields()
هو طلب منفصل للحصول على تفاصيل المكان، ويتم تحصيل رسومه وفقًا لأعلى رمز تخزين تعريفي بين
الحقول التي يطلبها. ويعتمد توفير المال من خلال هذا النهج على عدد الأماكن التي يفتحها المستخدمون.
الحقول التي تؤدي إلى تفعيل كل رمز تخزين تعريفي
تؤدي الحقول التالية إلى تفعيل رمز التخزين التعريفي Pro لميزة "البحث في الجوار":
accessibilityOptions
addressComponents
adrFormatAddress
businessStatus
displayName
formattedAddress
googleMapsUri
iconBackgroundColor
id
location
photos
plusCode
svgIconMaskURI
types
utcOffsetMinutes
viewport
تؤدي الحقول التالية إلى تفعيل رمز التخزين التعريفي لميزة "البحث في الجوار" للمؤسسات:
internationalPhoneNumber
nationalPhoneNumber
priceLevel
rating
regularOpeningHours
userRatingCount
websiteURIتؤدي الحقول التالية إلى تفعيل رمز التخزين التعريفي Enterprise + Atmosphere لميزة "البحث في الجوار":
allowsDogs
editorialSummary
evChargeOptions
fuelOptions
hasCurbsidePickup
hasDelivery
hasDineIn
hasLiveMusic
hasMenuForChildren
hasOutdoorSeating
hasRestroom
hasTakeout
hasWifi
isGoodForChildren
isGoodForGroups
isGoodForWatchingSports
isReservable
parkingOptions
paymentOptions
reviews
servesBeer
servesBreakfast
servesBrunch
servesCocktails
servesCoffee
servesDessert
servesDinner
servesLunch
servesVegetarianFood
servesWine
للاطّلاع على رمز التخزين التعريفي لكل حقل، يُرجى مراجعة حقول بيانات فئة المكان.