Google Maps API - 最近的标记函数更改为最近的 n 个标记

Posted

技术标签:

【中文标题】Google Maps API - 最近的标记函数更改为最近的 n 个标记【英文标题】:Google Maps API - Closest marker function change to closest n markers 【发布时间】:2015-03-10 10:20:15 【问题描述】:

我正在使用this question 中的公式来查找地图上离当前位置最近的标记。我想修改这个公式,以便它找到壁橱n 位置数(最近的 5 个位置,最近的 10 个位置等),但我不知道如何完成。

这是我使用的修改后的公式:

function rad(x) return x*Math.PI/180;
function find_closest_marker(center, map) 
    var lat = center.lat();
    var lng = center.lng();
    var R = 6371; // radius of earth in km
    var distances = [];
    var closest = -1;
    for( i=0;i<markers.length; i++ ) 
        var mlat = markers[i].position.lat();
        var mlng = markers[i].position.lng();
        var dLat  = rad(mlat - lat);
        var dLong = rad(mlng - lng);
        var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
            Math.cos(rad(lat)) * Math.cos(rad(lat)) * Math.sin(dLong/2) * Math.sin(dLong/2);
        var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
        var d = R * c;
        distances[i] = d;
        if ( closest == -1 || d < distances[closest] ) 
            closest = i;
        
    

    //Log title of closest marker
    console.log(markers[closest].title);

这是我加载标记的方式:

// Add markers to the map
function setMarkers(center, map) 
    var json = (function ()  
        var json = null; 
        $.ajax( 
            'async': false, 
            'global': false, 
            'url': "js/data.json", 
            'dataType': "json", 
            'success': function (data) 
                 json = data; 
             
        );
        return json;
    )();
    // Loop over each of the json elements
    for (var i = 0, length = json.length; i < length; i++) 
        var data = json[i],
        latLng = new google.maps.LatLng(data.lat, data.lon);
        // Create a marker and place it on the map
        var icon = 'assets/marker.png';
        var marker = new google.maps.Marker(
            position: latLng,
            map: map,
            icon: icon,
            title: data.loc
        );
        markers.push(marker);
        infoBox(map, marker, data);
    

如何进一步修改公式,以便找到最接近的 n 标记数,而不仅仅是单个最接近的标记?

【问题讨论】:

【参考方案1】:

您可以使用(稍作修改)this question 中的 findClosestN 函数(将 gmarkers 更改为 markers,将函数更改为返回仅限于 numberOfResults 元素的 closest 数组)

function findClosestN(pt, numberOfResults) 
    var closest = [];
    for (var i = 0; i < markers.length; i++) 
        markers[i].distance = google.maps.geometry.spherical.computeDistanceBetween(pt, markers[i].getPosition());
        markers[i].setMap(null);
        closest.push(markers[i]);
    
    closest.sort(sortByDist);
    return closest.splice(0,numberOfResults);


function sortByDist(a, b) 
    return (a.distance - b.distance)

proof of concept fiddle

代码 sn-p:

var geocoder = null;
var map = null;
var customerMarker = null;
var markers = [];
var closest = [];

function initialize() 
  // alert("init");
  geocoder = new google.maps.Geocoder();
  map = new google.maps.Map(document.getElementById('map'), 
    zoom: 9,
    center: new google.maps.LatLng(52.6699927, -0.7274620),
    mapTypeId: google.maps.MapTypeId.ROADMAP
  );
  var infowindow = new google.maps.InfoWindow();
  var marker, i;
  var bounds = new google.maps.LatLngBounds();
  document.getElementById('info').innerhtml = "found " + locations.length + " locations<br>";
  for (i = 0; i < locations.length; i++) 
    var coordStr = locations[i][4];
    var coords = coordStr.split(",");
    var pt = new google.maps.LatLng(parseFloat(coords[0]), parseFloat(coords[1]));
    bounds.extend(pt);
    marker = new google.maps.Marker(
      position: pt,
      map: map,
      icon: locations[i][5],
      address: locations[i][2],
      title: locations[i][0],
      html: locations[i][0] + "<br>" + locations[i][2]
    );
    markers.push(marker);
    google.maps.event.addListener(marker, 'click', (function(marker, i) 
        return function() 
          infowindow.setContent(marker.html);
          infowindow.open(map, marker);
        
      )
      (marker, i));
  
  map.fitBounds(bounds);



function codeAddress() 
  var address = document.getElementById('address').value;
  geocoder.geocode(
    'address': address
  , function(results, status) 
    if (status == google.maps.GeocoderStatus.OK) 
      map.setCenter(results[0].geometry.location);
      if (customerMarker) customerMarker.setMap(null);
      customerMarker = new google.maps.Marker(
        map: map,
        position: results[0].geometry.location
      );
      for (var i = 0; i < markers.length; i++) 
        markers[i].setMap(null);
      
      var numResults = parseInt(document.getElementById('numberResults').value);
      closest = findClosestN(results[0].geometry.location, numResults);
      for (var i = 0; i < closest.length; i++) 
        closest[i].setMap(map);
      
     else 
      alert('Geocode was not successful for the following reason: ' + status);
    
  );


function findClosestN(pt, numberOfResults) 
  var closest = [];
  for (var i = 0; i < markers.length; i++) 
    markers[i].distance = google.maps.geometry.spherical.computeDistanceBetween(pt, markers[i].getPosition());
    markers[i].setMap(null);
    closest.push(markers[i]);
  
  closest.sort(sortByDist);
  return closest.splice(0, numberOfResults);


function sortByDist(a, b) 
  return (a.distance - b.distance)


google.maps.event.addDomListener(window, 'load', initialize);

var locations = [
  ["John's Pizza", "no", "400 University Ave, Palo Alto, CA", "<Polygon><outerBoundaryIs><LinearRing><coordinates>-122.121277,37.386799,0 -122.158012,37.4168,0 -122.158012,37.448151,0 -122.142906,37.456055,0 -122.118874,37.45224,0 -122.107544,37.437793,0 -122.102737,37.422526,0 -122.113037,37.414618,0 -122.121277,37.386799,0   </coordinates></LinearRing></outerBoundaryIs></Polygon>", "37.447038,-122.160575", "http://maps.google.com/mapfiles/ms/icons/blue.png"],
  ["JJs Express", "yes", "1000 Santa Cruz Ave, Menlo Park, CA", "<Polygon><outerBoundaryIs><LinearRing><coordinates>-122.200928,37.438611,0 -122.158012,37.4168,0 -122.158012,37.448151,0 -122.142906,37.456055,0 -122.144623,37.475948,0 -122.164192,37.481125,0 -122.189255,37.478673,0 -122.208481,37.468319,0 -122.201271,37.438338,0 </coordinates></LinearRing></outerBoundaryIs></Polygon>", "37.448638,-122.187176", "http://maps.google.com/mapfiles/ms/icons/green.png"],
  ["John Paul's Pizzeria", "no", "1100 El Camino Real, Belmont, CA", "<Polygon><outerBoundaryIs><LinearRing><coordinates>-122.304268,37.516534,0 -122.300835,37.505096,0 -122.262383,37.481669,0 -122.242813,37.502917,0 -122.244186,37.534232,0 -122.269249,37.550021,0 -122.291222,37.545122,0 -122.302895,37.537499,0 -122.304268,37.516534,0 </coordinates></LinearRing></outerBoundaryIs></Polygon>", "37.520436,-122.275978", "http://maps.google.com/mapfiles/ms/icons/red.png"],
  ["JJs Express", "yes", "300 E 4th Ave, San Mateo, CA", "<Polygon><outerBoundaryIs><LinearRing><coordinates>-122.304268,37.516534,0 -122.348557,37.538044,0 -122.359886,37.56363,0 -122.364006,37.582405,0 -122.33654,37.589207,0 -122.281609,37.570433,0 -122.291222,37.545122,0 -122.302895,37.537499,0 -122.304268,37.516534,0 </coordinates></LinearRing></outerBoundaryIs></Polygon>", "37.564435,-122.322080", "http://maps.google.com/mapfiles/ms/icons/green.png"],
  ["John's Pizza", "yes", "1400 Broadway Ave, Burlingame, CA", "<Polygon><outerBoundaryIs><LinearRing><coordinates>-122.374306,37.548933,0 -122.348557,37.538044,0 -122.359886,37.56363,0 -122.364006,37.582405,0 -122.33654,37.589207,0 -122.359543,37.59764,0 -122.372246,37.604712,0 -122.417564,37.594648,0 -122.374306,37.548933,0 </coordinates></LinearRing></outerBoundaryIs></Polygon>", "37.584935,-122.366182", "http://maps.google.com/mapfiles/ms/icons/blue.png"],
  ["JJs Express", "yes", "700 San Bruno Ave, San Bruno, CA", "<Polygon><outerBoundaryIs><LinearRing><coordinates>-122.462883,37.628916,0 -122.445374,37.639247,0 -122.426147,37.648762,0 -122.405205,37.642238,0 -122.400055,37.628644,0 -122.392159,37.610696,0 -122.372246,37.604712,0 -122.417564,37.594648,0 -122.462196,37.628644,0  </coordinates></LinearRing></outerBoundaryIs></Polygon>", "37.630934,-122.406883", "http://maps.google.com/mapfiles/ms/icons/green.png"],
  ["JJs Express", "yes", "300 Beach St, San Francisco, CA", "<Polygon><outerBoundaryIs><LinearRing><coordinates>-122.43576,37.790795,0 -122.449493,37.801646,0 -122.425461,37.809784,0 -122.402115,37.811411,0 -122.390442,37.794593,0 -122.408295,37.79188,0 -122.434387,37.789167,0 </coordinates></LinearRing></outerBoundaryIs></Polygon>", "37.807628,-122.413782", "http://maps.google.com/mapfiles/ms/icons/green.png"],
  ["JJs Express", "yes", "1400 Haight St, San Francisco, CA", "<Polygon><outerBoundaryIs><LinearRing><coordinates>-122.463398,37.760266,0 -122.477349,37.774785,0 -122.427349,37.774785,0 -122.429237,37.763658,0 -122.46357,37.760808,0</coordinates></LinearRing></outerBoundaryIs></Polygon>", "37.770129,-122.445082", "http://maps.google.com/mapfiles/ms/icons/green.png"],
  ["JJs Express", "yes", "2400 Mission St, San Francisco, CA", "<Polygon><outerBoundaryIs><LinearRing><coordinates>-122.418766,37.747779,0 -122.425289,37.768951,0 -122.406063,37.769901,0 -122.406063,37.749679,0 -122.418251,37.747508,0 </coordinates></LinearRing></outerBoundaryIs></Polygon>", "37.758630,-122.419082", "http://maps.google.com/mapfiles/ms/icons/green.png"],
  ["JJs Express", "yes", "500 Castro St, Mountain View, CA", "<Polygon><outerBoundaryIs><LinearRing><coordinates>-122.121277,37.386799,0 -122.108917,37.362244,0 -122.077675,37.3385,0 -122.064285,37.378615,0 -122.069778,37.3898,0 -122.076645,37.402619,0 -122.078705,37.411619,0 -122.113037,37.414618,0 -122.121277,37.386799,0  </coordinates></LinearRing></outerBoundaryIs></Polygon>", "37.390040,-122.081573", "http://maps.google.com/mapfiles/ms/icons/green.png"],
  ["John's Pizza", "no", "100 S Murphy Ave, Sunnyvale, CA", "<Polygon><outerBoundaryIs><LinearRing><coordinates>-122.047119,37.33113,0 -122.065315,37.332495,0 -122.077675,37.3385,0 -122.064285,37.378615,0 -122.036819,37.385162,0 -122.006607,37.382162,0 -122.00386,37.342048,0 -122.047119,37.331403,0  </coordinates></LinearRing></outerBoundaryIs></Polygon>", "37.377441,-122.030071", "http://maps.google.com/mapfiles/ms/icons/blue.png"],
  ["John's Pizza", "no", "1200 Curtner Ave, San Jose, CA", "<Polygon><outerBoundaryIs><LinearRing><coordinates>-121.935196,37.345051,0 -121.931076,37.294267,0 -121.871338,37.293721,0 -121.806793,37.293174,0 -121.798553,37.361426,0 -121.879578,37.36088,0 -121.934509,37.345597,0 -121.935196,37.345051,0 </coordinates></LinearRing></outerBoundaryIs></Polygon>", "37.288742,-121.890765", "http://maps.google.com/mapfiles/ms/icons/blue.png"],
  ["John's Pizza", "yes", "700 Blossom Hill Rd, San Jose, CA", "<Polygon><outerBoundaryIs><LinearRing><coordinates>-121.935883,37.253287,0 -121.931076,37.294267,0 -121.871338,37.293721,0 -121.806793,37.293174,0 -121.790657,37.234702,0 -121.852455,37.223221,0 -121.935539,37.253014,0 </coordinates></LinearRing></outerBoundaryIs></Polygon>", "37.250543,-121.846563", "http://maps.google.com/mapfiles/ms/icons/blue.png"],
  ["John's Pizza", "yes", "100 N Milpitas Blvd, Milpitas, CA", "<Polygon><outerBoundaryIs><LinearRing><coordinates>-121.947556,37.435612,0 -121.934509,37.476493,0 -121.893311,37.469409,0 -121.852798,37.429615,0 -121.843872,37.400165,0 -121.887817,37.3898,0 -121.959915,37.420345,0 -121.959915,37.427979,0 -121.948929,37.435612,0 -121.947556,37.435612,0</coordinates></LinearRing></outerBoundaryIs></Polygon>", "37.434113,-121.901139", "http://maps.google.com/mapfiles/ms/icons/blue.png"],
  ["John's Pizza", "yes", "3300 Mowry Blvd, Fremont, CA", "<Polygon><outerBoundaryIs><LinearRing><coordinates>-122.02343,37.52198,0 -122.023773,37.558731,0 -121.989784,37.573426,0 -121.959572,37.566351,0 -121.944466,37.544305,0 -121.967125,37.520891,0 -122.023087,37.522525,0</coordinates></LinearRing></outerBoundaryIs></Polygon>", "37.552773,-121.985153", "http://maps.google.com/mapfiles/ms/icons/blue.png"]
];
html,
body,
table,
tbody,
#map 
  height: 100%;
  width: 100%;
  padding: 0;
  margin: 0;
<script src="https://maps.googleapis.com/maps/api/js?libraries=geometry,places&key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk"></script>
<table border="1" style="height: 90%; width:100%;">
  <tr style="height: 100%; width:100%;">
    <td style="height: 100%; width:100%;">
      <div id="map"></div>
    </td>
    <td>
      <div id="side_bar"></div>
    </td>
  </tr>
</table>
<input id="address" type="text" value="Palo Alto, CA" />
<input id="numberResults" type="text" value="5" />
<input type="button" value="Search" onclick="codeAddress();" />
<div id="info"></div>

【讨论】:

以上是关于Google Maps API - 最近的标记函数更改为最近的 n 个标记的主要内容,如果未能解决你的问题,请参考以下文章

google maps js v3 api教程 -- 在地图上添加标记

在 google maps api v3 中隐藏方向服务中的标记

Google maps api v2如何找到最近的位置

Google Maps API - 如何仅绘制第一个和最后一个标记

如何在flutter中将标记从firebase(真实数据库)检索到新的google maps api

Google Maps API实施点击事件以获取目标元素