Google Maps JS API - 高级标记 - 仅显示最近的标记

问题描述 投票:0回答:1

我有以下 Google Maps API 代码,它在地图上显示来自邮政编码 JSON 列表的 AdvancedMarkers 标记。然后,当在表单中输入邮政编码(例如“SP4”)时,它会将自定义紫色标记放置到地图上,并继续显示 JSON 列表中的所有高级标记/邮政编码。

如何仅显示距输入位置/标记最近的 5 个高级标记/邮政编码?

<!doctype html>
<html>
  <head>
    <title>Geocoding Service</title>
    <script src="https://maps.googleapis.com/maps/api/js?key=API-KEY-GOES-HERE&region=GB&libraries=geometry,marker&callback=initMap&v=weekly" defer async></script>
    <script src="https://polyfill.io/v3/polyfill.min.js?features=default"></script>
    <style>
      /**
 * @license
 * Copyright 2019 Google LLC. All Rights Reserved.
 * SPDX-License-Identifier: Apache-2.0
 */
      /*
       * Always set the map height explicitly to define the size of the div element
       * that contains the map.
       */
      #map {
        width: 100%;
        height: 100%;
      }

      /*
       * Optional: Makes the sample page fill the window.
       */
      html,
      body {
        height: 100%;
        margin: 0;
        padding: 0;
      }

      input[type=text] {
        background-color: #fff;
        border: 0;
        border-radius: 2px;
        box-shadow: 0 1px 4px -1px rgba(0, 0, 0, 0.3);
        margin: 10px;
        padding: 0 0.5em;
        font: 400 18px Roboto, Arial, sans-serif;
        overflow: hidden;
        line-height: 40px;
        margin-right: 0;
        min-width: 25%;
      }

      input[type=button] {
        background-color: #fff;
        border: 0;
        border-radius: 2px;
        box-shadow: 0 1px 4px -1px rgba(0, 0, 0, 0.3);
        margin: 10px;
        padding: 0 0.5em;
        font: 400 18px Roboto, Arial, sans-serif;
        overflow: hidden;
        height: 40px;
        cursor: pointer;
        margin-left: 5px;
      }
      input[type=button]:hover {
        background: rgb(235, 235, 235);
      }
      input[type=button].button-primary {
        background-color: #1a73e8;
        color: white;
      }
      input[type=button].button-primary:hover {
        background-color: #1765cc;
      }
      input[type=button].button-secondary {
        background-color: white;
        color: #1a73e8;
      }
      input[type=button].button-secondary:hover {
        background-color: #d2e3fc;
      }

      #response-container {
        background-color: #fff;
        border: 0;
        border-radius: 2px;
        box-shadow: 0 1px 4px -1px rgba(0, 0, 0, 0.3);
        margin: 10px;
        padding: 0 0.5em;
        font: 400 18px Roboto, Arial, sans-serif;
        overflow: hidden;
        overflow: auto;
        max-height: 50%;
        max-width: 90%;
        background-color: rgba(255, 255, 255, 0.95);
        font-size: small;
      }

      #instructions {
        background-color: #fff;
        border: 0;
        border-radius: 2px;
        box-shadow: 0 1px 4px -1px rgba(0, 0, 0, 0.3);
        margin: 10px;
        padding: 0 0.5em;
        font: 400 18px Roboto, Arial, sans-serif;
        overflow: hidden;
        padding: 1rem;
        font-size: medium;
      }
    </style>

  </head>
  <body>
    <div>
      <label for="postcodeInput">Enter Postcode</label>
      <input type="text" id="postcodeInput">
      <button id="submitButton" onclick="findNearestMarkers()">Submit</button>
    </div>
    <div id="map"></div>
    <script>
      /**
       * @license
       * Copyright 2019 Google LLC. All Rights Reserved.
       * SPDX-License-Identifier: Apache-2.0
       */
              // @ts-nocheck TODO remove when fixed

      let map;
      let marker;
      let markers = [];
      let geocoder;
      let jsonMapData;


      async function initMap() {

        const { Map } = await google.maps.importLibrary("maps");
        const { AdvancedMarkerElement, PinElement } = await google.maps.importLibrary("marker");

        map = new Map(document.getElementById("map"), {
          zoom: 6,
          center: {lat: 54.11202, lng: -5.19578},
          mapId: "DEMO_MAP_ID",
          mapTypeControl: false,
        });

        const postcodeInput = document.getElementById('postcodeInput').value;
        const submitBtn = document.getElementById('submitButton');

        const jsonMapData = {
          "data": [{"Postcode": "SP11DE", "PinColour": "#008000"}, {"Postcode": "SP12AJ", "PinColour": "#FFBF00"}, {"Postcode": "SP12AJ", "PinColour": "#FF0000"}, {"Postcode": "SP12AQ", "PinColour": "#008000"}, {"Postcode": "SP12AQ", "PinColour": "#FFBF00"}, {"Postcode": "SP12LP", "PinColour": "#008000"}, {"Postcode": "SP12LP", "PinColour": "#008000"}, {"Postcode": "SP12TJ", "PinColour": "#FF0000"}, {"Postcode": "SP27EJ", "PinColour": "#008000"}, {"Postcode": "SP27EJ", "PinColour": "#FF0000"}, {"Postcode": "SP27EJ", "PinColour": "#FFBF00"}, {"Postcode": "SP27NP", "PinColour": "#FFBF00"}, {"Postcode": "SP27NP", "PinColour": "#FFBF00"}, {"Postcode": "SP54JA", "PinColour": "#FFBF00"}, {"Postcode": "SP12BP", "PinColour": "#FFBF00"}, {"Postcode": "SP12BP", "PinColour": "#FFBF00"}, {"Postcode": "SP12QB", "PinColour": "#FFBF00"}, {"Postcode": "SP13ST", "PinColour": "#FFBF00"}, {"Postcode": "SP13ST", "PinColour": "#FFBF00"}, {"Postcode": "SP13ST", "PinColour": "#FFBF00"}, {"Postcode": "SP13TS", "PinColour": "#FFBF00"}, {"Postcode": "SP13TS", "PinColour": "#FFBF00"}, {"Postcode": "SP27PY", "PinColour": "#FFBF00"}, {"Postcode": "SP27SU", "PinColour": "#FFBF00"}, {"Postcode": "SP27YS", "PinColour": "#FFBF00"}, {"Postcode": "SP27YS", "PinColour": "#FFBF00"}, {"Postcode": "SP27YS"}, {"Postcode": "SP27YS", "PinColour": "#FFBF00"}, {"Postcode": "SP27YS", "PinColour": "#FFBF00"}, {"Postcode": "SP28BJ", "PinColour": "#FFBF00"}, {"Postcode": "SP28RH", "PinColour": "#FFBF00"}, {"Postcode": "SP29LE", "PinColour": "#FFBF00"}, {"Postcode": "SP29LE", "PinColour": "#FFBF00"}, {"Postcode": "SP11DP", "PinColour": "#FFBF00"}, {"Postcode": "SP11DP", "PinColour": "#FFBF00"}, {"Postcode": "SP11DP", "PinColour": "#FFBF00"}, {"Postcode": "SP12DD", "PinColour": "#FFBF00"}, {"Postcode": "SP12DD", "PinColour": "#FFBF00"}, {"Postcode": "SP12PU", "PinColour": "#FFBF00"}, {"Postcode": "SP12PU", "PinColour": "#FFBF00"}, {"Postcode": "SP12PU", "PinColour": "#FFBF00"}, {"Postcode": "SP12PU", "PinColour": "#FFBF00"}, {"Postcode": "SP12PU", "PinColour": "#FFBF00"}, {"Postcode": "SP12PU", "PinColour": "#FFBF00"}, {"Postcode": "SP12PU", "PinColour": "#FFBF00"}, {"Postcode": "SP13QS", "PinColour": "#FFBF00"}, {"Postcode": "SP27NU", "PinColour": "#FFBF00"}]
        };

        // Loop through the postcode data array
        jsonMapData.data.forEach(postcodeData => {
          const postcode = postcodeData.Postcode;
          const pinColour = postcodeData.PinColour;
          console.log(pinColour);

          //Geocode the entered postcode
          const geocoder = new google.maps.Geocoder();
          geocoder.geocode({address: postcode + ', UK'}, (results, status) => {
            if (status === 'OK' && results[0]) {
              // create a marker for each postcode
              const marker = new google.maps.marker.AdvancedMarkerElement({
                position: results[0].geometry.location,
                map: map,
                content: new PinElement({
                  background: pinColour,
                  borderColor: "#FFF",
                  glyphColor: "white"
                }).element,
              });
              markers.push(marker);
              console.log(marker);
            } else {
              console.error('Geocode was not successful for the following reason: ' + status);
            }
          });
        });
        //.catch(error => console.error('Error loading JSON data: ', error));
      }

      function findNearestMarkers() {
        const postcodeInput = document.getElementById('postcodeInput').value;

        // Geocode the entered postcode
        const geocoder = new google.maps.Geocoder();
        geocoder.geocode({ address: postcodeInput + ', UK' }, (results, status) => {
          if (status === 'OK' && results[0]) {
            const enteredLocation = results[0].geometry.location;

            // Create a marker for the entered location
            const enteredLocationMarker = new google.maps.Marker({
              position: enteredLocation,
              map: map,
              title: postcodeInput,
              icon: 'https://maps.google.com/mapfiles/ms/icons/purple-dot.png'
            });

            // Set map center and zoom to enetered location
            map.setCenter(enteredLocation);
            map.setZoom(11);

            // Filter nearest markers
            const nearestMarkers = markers.filter(marker => {
              const markerLocation = marker.position;
              const distance = google.maps.geometry.spherical.computeDistanceBetween(enteredLocation, markerLocation);
              const miles = distance / 1609.34;
              return distance;
            });


            // Display nearest markers on map
            clearMarkers();

            nearestMarkers.forEach(marker => {
              marker.setMap(map);
            })

            // Log nearest markers as JSON in the console
            const nearestMarkersJSON = nearestMarkers.map(marker => ({
              Position: results[0].geometry.location
            }));
            console.log(JSON.stringify(nearestMarkersJSON));
          } else {
            console.error('Geocode was not successful for the following reason: ' + status);
          }
        });
      }

      // Clear all markers from map
      function clearMarkers() {
        markers.forEach(marker => {
          marker.setMap(null);
        });
      }

    </script>

  </body>
</html>
javascript google-maps-api-3 google-maps-markers geocode
1个回答
1
投票

要仅显示距输入位置最近的 5 个标记,您可以按如下方式修改

findNearestMarkers
函数:

function findNearestMarkers() {
  const postcodeInput = document.getElementById('postcodeInput').value;

  // Geocode the entered postcode
  const geocoder = new google.maps.Geocoder();
  geocoder.geocode({ address: postcodeInput + ', UK' }, (results, status) => {
    if (status === 'OK' && results[0]) {
      const enteredLocation = results[0].geometry.location;

      // Calculate distances to all markers and store them in an array of objects
      const distances = markers.map(marker => {
        const markerLocation = marker.position;
        const distance = google.maps.geometry.spherical.computeDistanceBetween(enteredLocation, markerLocation);
        return { marker, distance };
      });

      // Sort the distances array by distance in ascending order
      distances.sort((a, b) => a.distance - b.distance);

      // Get the nearest 5 markers
      const nearestMarkers = distances.slice(0, 5).map(item => item.marker);

      // Create an icon for the entered location
      const enteredLocationIcon = {
        url: 'https://maps.google.com/mapfiles/ms/icons/purple-dot.png',
        scaledSize: new google.maps.Size(32, 32), // Adjust the size as needed
      };

      // Create a marker for the entered location
      const enteredLocationMarker = new google.maps.Marker({
        position: enteredLocation,
        map: map,
        title: postcodeInput,
        icon: enteredLocationIcon,
      });

      // Set map center and zoom to the entered location
      map.setCenter(enteredLocation);
      map.setZoom(11);

      // Clear existing markers from the map
      clearMarkers();

      // Display nearest markers on the map
      nearestMarkers.forEach(marker => {
        marker.setMap(map);
      });

      // Log nearest markers as JSON in the console
      const nearestMarkersJSON = nearestMarkers.map(marker => ({
        Position: marker.getPosition().toJSON(),
      }));
      console.log(JSON.stringify(nearestMarkersJSON));
    } else {
      console.error('Geocode was not successful for the following reason: ' + status);
    }
  });



How to implement marker clustering in your code:

**Step 1:** To make your map more efficient and user-friendly when you have a large number of markers, you can use the "MarkerClusterer" library provided by Google Maps. This library helps group nearby markers together.

To get started, you'll need to include this library in your HTML file. You can do this by adding the following code inside your HTML `<head>` section:

```html
<script src="https://developers.google.com/maps/documentation/javascript/examples/markerclusterer/markerclusterer.js"></script>

第2步:现在,让我们使用这个库。创建地图并添加所有标记后,您需要初始化 MarkerClusterer 以启用标记聚类。以下是修改

initMap
函数的方法:

async function initMap() {
  // ... Your existing code ...

  // Create an array to keep track of your marker objects
  const markers = [];

  // Loop through your postcode data
  jsonMapData.data.forEach(postcodeData => {
    // ... Your existing code for creating markers ...

    markers.push(marker); // Add each marker to the markers array
  });

  // Initialize the MarkerClusterer
  const markerCluster = new MarkerClusterer(map, markers, {
    imagePath: "https://developers.google.com/maps/documentation/javascript/examples/markerclusterer/m",
  });
}

在此更新的代码中,我们首先创建一个名为

markers
的数组来存储标记对象。然后,当您循环邮政编码数据并创建标记时,您可以将每个标记添加到该数组中。

最后,我们用您的地图和

MarkerClusterer
数组初始化
markers
。这会自动将附近的标记分组为簇,使您的地图更加高效且用户友好,特别是在处理大量标记时。

© www.soinside.com 2019 - 2024. All rights reserved.