【问题标题】:google maps api v3 how to rank by closest distancegoogle maps api v3如何按最近距离排名
【发布时间】:2012-05-30 09:22:06
【问题描述】:

有谁知道如何使用此处提到的按距离搜索排名选项? https://developers.google.com/maps/documentation/javascript/places#place_search_requests

在请求选项中列出这个似乎不起作用。这是我与此相关的代码部分:

var request = {
  location: coords,
  //radius: 30000,
  keyword: ['puma, retail'],
  types: ['store'],
  rankBy: google.maps.places.RankBy.DISTANCE
};

service = new google.maps.places.PlacesService(map);
service.search(request, callback);

function callback(results, status) {
    if (status == google.maps.places.PlacesServiceStatus.OK) {
        for (var i = 0; i < results.length; i++) {
            createMarker(results[i]);
                            listResults(results[i]);
        }
    } 
}

如果我包含半径,代码将定位并列出结果,但结果未按距离升序列出。谷歌的文档说,如果使用 rankBy 选项,也不需要半径。我错过了什么吗?

【问题讨论】:

  • 我在同一条船上...寻找解决方案。

标签: google-maps search rank


【解决方案1】:

您不能同时使用 radius 和 RankBy.DISTANCE 属性。因此,您有两种选择:

1) 按半径搜索,然后在您自己的代码中按距离对结果进行排序。

例子:

var request = {
               location: coords,
               radius: 30000,
               keyword: ['puma, retail'],
               types: ['store']
               };
service = new google.maps.places.PlacesService(map);
service.search(request, callback);

function callback(results, status) {
         if (status == google.maps.places.PlacesServiceStatus.OK) {
          for (var i = 0; i < results.length; i++) {
           sortresults(results[i]);//sortresult uses haversine to calcuate distance and then arranges the result in the order of distance
           createMarker(results[i]);
           listResults(results[i]);
       }
   } 
}

选项 2:按 RankBy.Distance 搜索,然后使用半径限制结果。同样,您需要使用半正弦公式来计算距离。

var request = {
               location: coords,
               rankBy: google.maps.places.RankBy.DISTANCE,
               keyword: ['puma, retail'],
               types: ['store']
               };
service = new google.maps.places.PlacesService(map);
service.search(request, callback);

function callback(results, status) {
         if (status == google.maps.places.PlacesServiceStatus.OK) {

           for (var i = 0; i < results.length; i++) {
           d= distance(coords,results[i].latlng)
           if(d<rd)
            {createMarker(results[i]);
             listResults(results[i]);
            }
           }
   } 
}

//Returns Distance between two latlng objects using haversine formula
distance(p1, p2) {
 if (!p1 || !p2) 
  return 0;
 var R = 6371000; // Radius of the Earth in m
 var dLat = (p2.lat() - p1.lat()) * Math.PI / 180;
 var dLon = (p2.lng() - p1.lng()) * Math.PI / 180;
 var a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
 Math.cos(p1.lat() * Math.PI / 180) * Math.cos(p2.lat() * Math.PI / 180) *
 Math.sin(dLon / 2) * Math.sin(dLon / 2);
 var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
 var d = R * c;
 return d;
 }

【讨论】:

  • 这对我来说绝对是正确的答案,我遇到了和@JFlo一样的问题
【解决方案2】:

请注意,在当前的 Api Doc 中 PlacesService 类的“搜索”方法不可用

https://developers.google.com/maps/documentation/javascript/reference?hl=it#PlacesService

你必须选择:

  • nearbySearch(每页检索 20 个结果,最多 3 页)
  • radarSearch(检索 200 个结果,但细节较少)
  • 文本搜索(类似于附近搜索)

如果您选择 RankBy.DISTANCE,则无法设置半径

var request = {
  location: vLatLng,
  //radius: vRaggio,
  rankBy: google.maps.places.RankBy.DISTANCE,
  keyword: ['puma, retail'],
  types: ['store']
}

placesService.nearbySearch(request, function (data, status, placeSearchPagination) {
  if (status == google.maps.places.PlacesServiceStatus.OK) {
  //...
  // do your stuffs with data results
  //...
  if (placeSearchPagination && placeSearchPagination.hasNextPage) {
    placeSearchPagination.nextPage();
  } 
});

如果要根据距离半径限制数据,可以使用此功能检查结果是否太远。

function checkRadiusDistance(place,centerLatLng,radius) {
  return google.maps.geometry.spherical.computeDistanceBetween(place.geometry.location, centerLatLng) < radius;
});

请注意,这也是获取某个半径内的地点的唯一方法,因为当您指定“rankBy:google.maps.places.RankBy.PROMINENCE”时以及“radius=xx”placesService 为您提供在定义区域之外的结果

【讨论】:

    【解决方案3】:

    您不能同时使用 radius + rankBy 属性。

    如果您需要最近的位置,请选择一些类型,并设置 rankBy 属性。

    places.nearbySearch({
                            location: LatLng,
                            types: placeTypes,
                            rankBy: google.maps.places.RankBy.DISTANCE
                        },
                        function (results) {
                            // process the results, r[0] is the closest place
                        }
                    );
    

    你可以在哪里设置这样的placeTypes

    var placeTypes = [
    'accounting',
    'airport',
    'amusement_park',
    'aquarium',
    'art_gallery',
    'atm',
    'bakery',
    'bank',
    'bar',
    'beauty_salon',
    'bicycle_store',
    'book_store',
    'bowling_alley',
    'bus_station',
    'cafe',
    'campground',
    'car_dealer',
    'car_rental',
    'car_repair',
    'car_wash',
    'casino',
    'cemetery',
    'church',
    'city_hall',
    'clothing_store',
    'convenience_store',
    'courthouse',
    'dentist',
    'department_store',
    'doctor',
    'electrician',
    'electronics_store',
    'embassy',
    'establishment',
    'finance',
    'fire_station',
    'florist',
    'food',
    'funeral_home',
    'furniture_store',
    'gas_station',
    'general_contractor',
    'grocery_or_supermarket',
    'gym',
    'hair_care',
    'hardware_store',
    'health',
    'hindu_temple',
    'home_goods_store',
    'hospital',
    'insurance_agency',
    'jewelry_store',
    'laundry',
    'lawyer',
    'library',
    'liquor_store',
    'local_government_office',
    'locksmith',
    'lodging',
    'meal_delivery',
    'meal_takeaway',
    'mosque',
    'movie_rental',
    'movie_theater',
    'moving_company',
    'museum',
    'night_club',
    'painter',
    'park',
    'parking',
    'pet_store',
    'pharmacy',
    'physiotherapist',
    'place_of_worship',
    'plumber',
    'police',
    'post_office',
    'real_estate_agency',
    'restaurant',
    'roofing_contractor',
    'rv_park',
    'school',
    'shoe_store',
    'shopping_mall',
    'spa',
    'stadium',
    'storage',
    'store',
    'subway_station',
    'synagogue',
    'taxi_stand',
    'train_station',
    'travel_agency',
    'university',
    'veterinary_care',
    'zoo'
    

    ];

    【讨论】:

      【解决方案4】:

      遇到了同样的问题。 根据此来源:http://www.geocodezip.com/v3_GoogleEx_place-search.html 我能够这样制定查询:

      var request = {
      location: gps,
      types: ['food'], //You can substitute "keyword: 'food'," (without double-quotes) here as well.
      rankBy: google.maps.places.RankBy.DISTANCE, //Note there is no quotes here, I made that mistake.
      key: key 
      };
      

      Var key 是 API 密钥,它不是必需的,但添加以供以后使用。 GPS是:

      var gps = new google.maps.LatLng(location.lat,location.lon);
      

      最后,我做了你所做的一切,除了我在一张我不打算使用的地图上添加了边界。为此我做到了:

      var bounds = new google.maps.LatLngBounds();
      

      【讨论】:

      • 'types' 应该是 'type' 如果你想用变量替换值。否则,它将不起作用。