Tìm kiếm lân cận

Chọn nền tảng: Android iOS JavaScript Dịch vụ web
Nhà phát triển ở Khu vực kinh tế Châu Âu (EEA)

Tìm kiếm lân cận (Mới) lấy một hoặc nhiều loại địa điểm và trả về danh sách các địa điểm trùng khớp. Trong ví dụ sau, bạn có thể chọn một loại địa điểm và xem kết quả trên bản đồ. Nhấp vào các điểm đánh dấu để xem thêm thông tin chi tiết về các địa điểm.

Nearby Search (Mới) trả về thông tin về một nhóm địa điểm dựa trên các loại địa điểm mà bạn chỉ định – ví dụ: restaurant hoặc book_store hoặc bowling_alley. Dịch vụ này sẽ phản hồi bằng một danh sách các địa điểm phù hợp với các loại địa điểm được chỉ định trong bán kính của locationRestriction được chỉ định.

Để sử dụng Nearby Search (Mới), bạn phải bật "Places API (Mới)" trên dự án Google Cloud của mình. Hãy xem phần Bắt đầu sử dụng để biết thông tin chi tiết.

Tìm địa điểm lân cận

Gọi searchNearby() để trả về danh sách các địa điểm dựa trên các loại địa điểm, vị trí và bán kính đã chỉ định. Chỉ định các tham số tìm kiếm bằng cách sử dụng một yêu cầu, sau đó gọi searchNearby(). Kết quả được trả về dưới dạng danh sách các đối tượng Place, từ đó bạn có thể nhận được thông tin chi tiết về địa điểm. Đoạn mã sau đây cho thấy ví dụ về một yêu cầu và một lệnh gọi đến searchNearby():

TypeScript

// Get bounds and radius to constrain search.
center = mapElement.center;
let bounds = innerMap.getBounds();
const ne = bounds.getNorthEast();
const sw = bounds.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;
let bounds = innerMap.getBounds();
const ne = bounds.getNorthEast();
const sw = bounds.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);
  • Sử dụng tham số fields (bắt buộc) để chỉ định danh sách được phân tách bằng dấu phẩy gồm một hoặc nhiều trường dữ liệu.
  • Sử dụng tham số locationRestriction (bắt buộc) để chỉ định bán kính tối đa 50.000 mét.
  • Sử dụng tham số includedPrimaryTypes để chỉ định một hoặc nhiều loại địa điểm để tìm kiếm.
  • Sử dụng tham số rankPreference để chỉ định SearchNearbyRankPreferencePOPULARITY hoặc DISTANCE.
  • Xem danh sách đầy đủ các thông số.

Ví dụ:

Ví dụ sau đây sử dụng searchNearby() để truy vấn các địa điểm thuộc loại đã chọn trong phạm vi bản đồ và điền sẵn bản đồ bằng các điểm đánh dấu để cho thấy kết quả.

TypeScript

const mapElement = document.querySelector('gmp-map') as google.maps.MapElement;
let innerMap;
const advancedMarkerElement = document.querySelector('gmp-advanced-marker') as google.maps.marker.AdvancedMarkerElement;
let center;
let typeSelect;
let infoWindow;

async function initMap() {
    const { Map, InfoWindow } = await google.maps.importLibrary('maps') as google.maps.MapsLibrary;
    const { LatLng } = await google.maps.importLibrary("core") as google.maps.CoreLibrary;

    innerMap = mapElement.innerMap;
    innerMap.setOptions({
        mapTypeControl: false,
    });

    typeSelect = document.querySelector(".type-select");

    typeSelect.addEventListener('change', () => {
        nearbySearch();
    });

    infoWindow = new InfoWindow();

    // Kick off an initial search once map has loaded.
    google.maps.event.addListenerOnce(innerMap, 'idle', () => {
        nearbySearch();
    });
}

async function nearbySearch() {
    const { Place, SearchNearbyRankPreference } = await google.maps.importLibrary('places') as google.maps.PlacesLibrary;
    const { AdvancedMarkerElement } = await google.maps.importLibrary("marker") as google.maps.MarkerLibrary;
    const { spherical } = await google.maps.importLibrary('geometry') as google.maps.GeometryLibrary;
    // Get bounds and radius to constrain search.
    center = mapElement.center;
    let bounds = innerMap.getBounds();
    const ne = bounds.getNorthEast();
    const sw = bounds.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") as google.maps.CoreLibrary;
        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,
            });

            // 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.addListener('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,
    });
}

initMap();

JavaScript

const mapElement = document.querySelector('gmp-map');
let innerMap;
const advancedMarkerElement = document.querySelector('gmp-advanced-marker');
let center;
let typeSelect;
let infoWindow;
async function initMap() {
    const { Map, InfoWindow } = await google.maps.importLibrary('maps');
    const { LatLng } = await google.maps.importLibrary("core");
    innerMap = mapElement.innerMap;
    innerMap.setOptions({
        mapTypeControl: false,
    });
    typeSelect = document.querySelector(".type-select");
    typeSelect.addEventListener('change', () => {
        nearbySearch();
    });
    infoWindow = new InfoWindow();
    // Kick off an initial search once map has loaded.
    google.maps.event.addListenerOnce(innerMap, 'idle', () => {
        nearbySearch();
    });
}
async function nearbySearch() {
    const { Place, SearchNearbyRankPreference } = await google.maps.importLibrary('places');
    const { AdvancedMarkerElement } = await google.maps.importLibrary("marker");
    const { spherical } = await google.maps.importLibrary('geometry');
    // Get bounds and radius to constrain search.
    center = mapElement.center;
    let bounds = innerMap.getBounds();
    const ne = bounds.getNorthEast();
    const sw = bounds.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,
            });
            // 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.addListener('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,
    });
}
initMap();

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>
  <!-- prettier-ignore -->
  <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: "beta" });</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>

Dùng thử mẫu