O Nearby Search (novo) recebe um ou mais tipos de lugar e retorna uma lista de lugares correspondentes. No exemplo a seguir, você pode escolher um tipo de lugar e ver os resultados em um mapa. Clique nos marcadores para ver mais detalhes sobre os lugares.
O Nearby Search (novo) retorna informações sobre um conjunto de lugares com base nos tipos de lugar especificados por você (por exemplo restaurant, book_store ou bowling_alley). O serviço responde com uma lista de locais correspondentes aos tipos de lugares especificados no raio do locationRestriction definido.
Para usar o Nearby Search (novo), ative a "API Places (nova)" no projeto do Google Cloud. Consulte o artigo Começar para mais detalhes.
Encontrar lugares por perto
Chame searchNearby() para retornar uma lista de lugares com base nos tipos de lugares, local e raio especificados. Especifique os parâmetros de pesquisa usando uma solicitação e, em seguida, chame searchNearby(). Os resultados são retornados como uma lista de objetos Place, e nela você consegue os detalhes dos lugares.
O snippet a seguir mostra um exemplo de solicitação e chamada para 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);
- Use o parâmetro
fields(obrigatório) para especificar uma lista separada por vírgulas de um ou mais campos de dados. Os campos solicitados definem o preço da solicitação. Consulte Escolher campos de dados. - Use o parâmetro
locationRestriction(obrigatório) para especificar um raio de até 50.000 metros. - Use o parâmetro
includedPrimaryTypesao especificar um ou mais tipos de lugares para pesquisar. - Use o parâmetro
rankPreferencepara especificar umSearchNearbyRankPreferencedePOPULARITYouDISTANCE. - Veja a lista completa de parâmetros.
Exemplo
O exemplo a seguir usa searchNearby() para consultar lugares do tipo selecionado dentro dos limites do mapa e preenche um mapa com marcadores para mostrar os resultados.
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>Escolher campos de dados
Os campos solicitados definem o preço de cada solicitação de pesquisa. A solicitação é cobrada uma vez, na SKU mais alta entre os campos solicitados. Por exemplo, adicionar
reviews
a
fields
cobra toda a solicitação como Nearby Search Enterprise + Atmosphere.
Para manter as solicitações de pesquisa no Nearby Search Pro, solicite apenas os campos que os resultados da pesquisa mostram, como id, displayName, formattedAddress e location.
Quando um usuário selecionar um lugar, chame
fetchFields()
nele para receber campos como
reviews,
nationalPhoneNumber
ou
websiteURI.
Cada chamada de fetchFields() é uma solicitação separada do Place Details, faturada na SKU mais alta entre os campos solicitados. Se essa abordagem economiza dinheiro depende de quantos lugares os usuários abrem.
Campos que acionam cada SKU
Os campos a seguir acionam a SKU do Nearby Search Pro:
accessibilityOptions
addressComponents
adrFormatAddress
businessStatus
displayName
formattedAddress
googleMapsUri
iconBackgroundColor
id
location
photos
plusCode
svgIconMaskURI
types
utcOffsetMinutes
viewport
Os campos a seguir acionam a SKU Nearby Search Enterprise:
internationalPhoneNumber
nationalPhoneNumber
priceLevel
rating
regularOpeningHours
userRatingCount
websiteURIOs campos a seguir acionam a SKU Nearby Search 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
Para ver a SKU de cada campo, consulte Campos de dados da classe Place.