谷歌地图 - 查找给定半径内的所有标记 Javascript/Php
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/18512184/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Google Maps - Finding all the markers inside a given radius Javascript/Php
提问by compcobalt
I have this script that will show custom markers on a google map, but I would like to include a input text-box and be able to enter a city/state and a zip-code and see if there are any markers within lets say 400 miles from that city/state or zip-code. I would love it if the map can be dynamic so as you type out the city/state or zip-code it will show the results on the map by getting rid of all the other markers and leaving only the one that is within that radius, if that is too hard then a simple alter box saying what unit is the closest will also be OK :) I searched and found some say that I should load the geometry library and use computeDistanceBetween()
to find the distance of each marker from your center point but I have no idea how to do the zip-code part or how to put all of this together to work.
我有这个脚本可以在谷歌地图上显示自定义标记,但我想包含一个输入文本框,并且能够输入城市/州和邮政编码,看看是否有任何标记,比如 400距离该城市/州或邮政编码的英里。如果地图可以是动态的,我会喜欢它,这样当您输入城市/州或邮政编码时,它会通过删除所有其他标记并只留下该半径内的标记来在地图上显示结果,如果这太难了,那么一个简单的改变框说哪个单位最接近也可以:) 我搜索并发现有人说我应该加载几何库并使用它computeDistanceBetween()
来找到每个标记与中心点的距离,但我不知道如何处理邮政编码部分或如何将所有这些组合在一起工作。
Here is my code:
这是我的代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title></title>
<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script>
<script type="text/javascript" src="http://google-maps-utility-library-v3.googlecode.com/svn/trunk/markerclustererplus/src/markerclusterer.js"></script>
<script type="text/javascript">
var image = new google.maps.MarkerImage("marker-images/image.png",new google.maps.Size(40,35),new google.maps.Point(0,0),new google.maps.Point(20,35));
var shadow = new google.maps.MarkerImage(
'marker-images/shadow.png',
new google.maps.Size(62,35),
new google.maps.Point(0,0),
new google.maps.Point(20,35)
);
var shape = {
coord: [27,0,30,1,32,2,34,3,35,4,36,5,38,6,39,7,39,8,39,9,39,10,38,11,37,12,33,13,34,14,34,15,33,16,32,17,31,18,27,19,28,20,28,21,27,22,26,23,22,25,23,26,24,27,24,28,24,29,24,30,24,31,24,32,23,33,22,34,17,34,16,33,15,32,15,31,14,30,14,29,15,28,15,27,16,26,17,25,13,23,12,22,11,21,11,20,12,19,8,18,7,17,6,16,5,15,5,14,6,13,2,12,1,11,0,10,0,9,0,8,0,7,1,6,3,5,4,4,5,3,7,2,9,1,12,0,27,0],
type: 'poly'
};
// this variable will collect the html which will eventually be placed in the side_bar
var side_bar_html = "";
// arrays to hold copies of the markers and html used by the side_bar
// because the function closure trick doesnt work there
var gmarkers = [];
// global "map" variable
var map = null;
var circle = null;
//marker clusterer
var mc;
var mcOptions = {gridSize: 10, maxZoom: 8};
//global infowindow
var infowindow = new google.maps.InfoWindow();
//geocoder
var geocoder = new google.maps.Geocoder();
var address = new Array("41.8119,-87.6873",
"40.7888,-74.056",
"41.8119,-87.6873",
"48.6681,-97.3627",
"44.9793,-93.273",
"39.4857,-75.6775",
"41.8119,-87.6873",
"42.0203,-87.9059",
"32.7812,-96.7903",
"27.5159,-99.4941",
"32.7812,-96.7903",
"37.5608,-95.6684",
"41.8119,-87.6873",
"38.3763,-97.6702",
"42.2458,-83.2491",
"41.8122,-91.9139",
"41.8397,-88.0887",
"41.8397,-88.0887",
"38.5128,-122.787",
"41.8397,-88.0887",
"42.8863,-87.892",
"42.8863,-87.892",
"30.7539,-83.3321",
"39.889,-84.2422",
"34.106,-83.589");
var content = new Array("Unit No# 0206",
"Unit No# #2003",
"Unit No# 0176",
"Unit No# #2001",
"Unit No# 0124",
"Unit No# 0157",
"Unit No# #0162",
"Unit No# 0104",
"Unit No# 0118",
"Unit No# #2007",
"Unit No# 0112",
"Unit No# 0139",
"Unit No# 0205",
"Unit No# 0127",
"Unit No# 0187",
"Unit No# 0105",
"Unit No# 0214",
"Unit No# 0186",
"Unit No# 0173",
"Unit No# 0134",
"Unit No# 0128",
"Unit No# 0125",
"Unit No# 0158",
"Unit No# 0193",
"Unit No# 0201");
//min and max limits for multiplier, for random numbers
//keep the range pretty small, so markers are kept close by
var min = .999999;
var max = 1.000001;
function createMarker(latlng,text) {
var marker = new google.maps.Marker({
draggable: false,
raiseOnDrag: false,
icon: image,
shadow: shadow,
shape: shape,
position: latlng,
map: map
});
///get array of markers currently in cluster
var allMarkers = mc.getMarkers();
//check to see if any of the existing markers match the latlng of the new marker
if (allMarkers.length != 0) {
for (i=0; i < allMarkers.length; i++) {
var existingMarker = allMarkers[i];
var pos = existingMarker.getPosition();
if (latlng.equals(pos)) {
text = text + " & " + content[i];
}
}
}
google.maps.event.addListener(marker, 'click', function() {
infowindow.close();
infowindow.setContent(text);
infowindow.open(map,marker);
});
mc.addMarker(marker);
return marker;
}
function initialize(){
var options = {
zoom: 4,
center: new google.maps.LatLng(39.8282,-98.5795),
mapTypeId: google.maps.MapTypeId.ROADMAP
};
map = new google.maps.Map(document.getElementById('map'), options);
//marker cluster
var gmarkers = [];
mc = new MarkerClusterer(map, [], mcOptions);
for (i=0; i<address.length; i++) {
var ptStr = address[i];
var coords = ptStr.split(",");
var latlng = new google.maps.LatLng(parseFloat(coords[0]),parseFloat(coords[1]));
gmarkers.push(createMarker(latlng,content[i]));
}
}
function codeAddress() {
var address = document.getElementById('address').value;
var radius = parseInt(document.getElementById('radius').value, 10) * 1609.34;
geocoder.geocode( { 'address': address}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
map.setCenter(results[0].geometry.location);
var marker = new google.maps.Marker({
// map: map, <-- uncomment to show red marker
position: results[0].geometry.location
});
if (circle) circle.setMap(null);
circle = new google.maps.Circle({center:marker.getPosition(),
radius: radius,
fillOpacity: 0.35,
fillColor: "#FF0000",
map: map});
var bounds = new google.maps.LatLngBounds();
var foundMarkers = 0;
for (var i=0; i<gmarkers.length;i++) {
if (google.maps.geometry.spherical.computeDistanceBetween(gmarkers[i].getPosition(),marker.getPosition()) < radius) {
bounds.extend(gmarkers[i].getPosition())
gmarkers[i].setMap(map);
foundMarkers++;
} else {
gmarkers[i].setMap(null);
}
}
if (foundMarkers > 0) {
map.fitBounds(bounds);
} else {
map.fitBounds(circle.getBounds());
}
} else {
alert(status);
}
});
}
var infowindow = new google.maps.InfoWindow(
{
size: new google.maps.Size(150,50)
});
function handleKeyPress(e){
var key=e.keyCode || e.which;
if (key==13){
codeAddress();
}
}
function handleResetKeyPress(e){
if (map.getZoom() != 4) map.setZoom(4);
map.setCenter(new google.maps.LatLng(39.8282, -98.5795));
document.getElementById("address").value = 'Enter City,State or Zipcode';
document.getElementById("radius").value = '200';
}
</script>
<style>
html, body, #map {
height: 100%;
width: 100%;
margin: 0;
padding: 0;
}
.auto-style1 {
text-align: center;
}
#footer {
position : absolute;
bottom : 0;
height : 40px;
margin-top : 40px;
/* border: 1px solid blue; */
}
</style>
</head>
<body onload='initialize()'>
<div id="map"></div>
<div id="footer" class="auto-style1" style="left: 0px; bottom: 0; width: 100%">
<input type="text" id="address" value="Enter City,State or Zipcode" onclick="if(this.value=='Enter City,State or Zipcode'){this.value=''}" onblur="if(this.value==''){this.value='Enter City,State or Zipcode'}" onkeypress="handleKeyPress(event);" style="width: 183px">
<input type="button" value="Search" onclick="codeAddress();">
<input type="button" value="Reset" onclick="handleResetKeyPress();">
<input type="text" id="radius" value="200" style="width: 42px" onclick="if(this.value=='200'){this.value=''}" onblur="if(this.value==''){this.value='200'}" onkeypress="handleKeyPress(event);"> miles
</div>
</body>
</html>
采纳答案by max
Here is an example of how you could solve this with the geocoding API and some simple geometry.
下面是一个示例,说明如何使用地理编码 API 和一些简单的几何图形来解决此问题。
(Note that I have hardcoded the address and radius for brevity.)
(请注意,为简洁起见,我对地址和半径进行了硬编码。)
// we assume that you have an array of markers
var markers = [];
//In order to lookup the the position of a zip-code you can use the geocoding API:
// https://developers.google.com/maps/documentation/geocoding/
var geocode_api_base_url = "http://maps.googleapis.com/maps/api/geocode/json?";
var params = {
adress : 05673,
components : "country:us",
sensor : false
}
// This is the result set of markers in area
var in_area = [];
// http://maps.googleapis.com/maps/api/geocode/json?address=05673&components=country:US&sensor=false
$.getJSON( geocode_api_base_url + $.param(params), function(data) {
var location, search_area, in_area = [];
location = data['results'][0]['address_components']['geometry']['location'];
// We create a circle to look within:
search_area = {
strokeColor: '#FF0000',
strokeOpacity: 0.8,
strokeWeight: 2,
center : new google.maps.LatLng(location.lat, location.lon),
radius : 500
}
search_area = new google.maps.Circle(search_area);
$.each(markers, function(i,marker) {
if (google.maps.geometry.poly.containsLocation(marker.getPosition(), search_area)) {
in_area.push(marker);
}
});
console.info(in_area);
});
回答by Matej P.
Here is a working example.
这是一个工作示例。
The example uses all_locations
- array of example locations.
该示例使用all_locations
- 示例位置数组。
You can replace that with your locations (e.g. locations you fetch from your DB). You can insert any address to the input bar, e.g. '123 New Street, New York, 56789, NY' and using google.maps.Geocoder
the code will geocode that map into LatLng location around which it will draw a radius. Only locations that fall within the radius around the address will show on map. To see the example locations, input "Second Steet, New York" as address.
您可以将其替换为您的位置(例如,您从数据库中获取的位置)。您可以在输入栏中插入任何地址,例如“123 New Street, New York, 56789, NY”,然后使用google.maps.Geocoder
该代码将该地图地理编码为 LatLng 位置,并围绕该位置绘制半径。只有位于地址周围半径范围内的位置才会显示在地图上。要查看示例位置,请输入“Second Steet, New York”作为地址。
var map = null;
var radius_circle;
var markers_on_map = [];
var geocoder;
var infowindow;
//all_locations is just a sample, you will probably load those from database
var all_locations = [
{type: "Restaurant", name: "Restaurant 1", lat: 40.723080, lng: -73.984340},
{type: "School", name: "School 1", lat: 40.724705, lng: -73.986611},
{type: "School", name: "School 2", lat: 40.724165, lng: -73.983883},
{type: "Restaurant", name: "Restaurant 2", lat: 40.721819, lng: -73.991358},
{type: "School", name: "School 3", lat: 40.732056, lng: -73.998683}
];
//initialize map on document ready
$(document).ready(function(){
var latlng = new google.maps.LatLng(40.723080, -73.984340); //you can use any location as center on map startup
var myOptions = {
zoom: 1,
center: latlng,
mapTypeControl: true,
mapTypeControlOptions: {style: google.maps.MapTypeControlStyle.DROPDOWN_MENU},
navigationControl: true,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
geocoder = new google.maps.Geocoder();
google.maps.event.addListener(map, 'click', function(){
if(infowindow){
infowindow.setMap(null);
infowindow = null;
}
});
});
function showCloseLocations() {
var i;
var radius_km = $('#radius_km').val();
var address = $('#address').val();
//remove all radii and markers from map before displaying new ones
if (radius_circle) {
radius_circle.setMap(null);
radius_circle = null;
}
for (i = 0; i < markers_on_map.length; i++) {
if (markers_on_map[i]) {
markers_on_map[i].setMap(null);
markers_on_map[i] = null;
}
}
if (geocoder) {
geocoder.geocode({'address': address}, function (results, status) {
if (status == google.maps.GeocoderStatus.OK) {
if (status != google.maps.GeocoderStatus.ZERO_RESULTS) {
var address_lat_lng = results[0].geometry.location;
radius_circle = new google.maps.Circle({
center: address_lat_lng,
radius: radius_km * 1000,
clickable: false,
map: map
});
if (radius_circle) map.fitBounds(radius_circle.getBounds());
for (var j = 0; j < all_locations.length; j++) {
(function (location) {
var marker_lat_lng = new google.maps.LatLng(location.lat, location.lng);
var distance_from_location = google.maps.geometry.spherical.computeDistanceBetween(address_lat_lng, marker_lat_lng); //distance in meters between your location and the marker
if (distance_from_location <= radius_km * 1000) {
var new_marker = new google.maps.Marker({
position: marker_lat_lng,
map: map,
title: location.name
}); google.maps.event.addListener(new_marker, 'click', function () {
if(infowindow){
infowindow.setMap(null);
infowindow = null;
}
infowindow = new google.maps.InfoWindow(
{ content: '<div style="color:red">'+location.name +'</div>' + " is " + distance_from_location + " meters from my location",
size: new google.maps.Size(150,50),
pixelOffset: new google.maps.Size(0, -30)
, position: marker_lat_lng, map: map});
});
markers_on_map.push(new_marker);
}
})(all_locations[j]);
}
} else {
alert("No results found while geocoding!");
}
} else {
alert("Geocode was not successful: " + status);
}
});
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<script type="text/javascript">
google.load("maps", "3",{other_params:"sensor=false&libraries=geometry"});
</script>
<body style="margin:0px; padding:0px;" >
<input id="address" value="Second Steet, New York" placeholder="Input Address"/>
<select id="radius_km">
<option value=1>1km</option>
<option value=2>2km</option>
<option value=5>5km</option>
<option value=30>30km</option>
</select>
<button onClick="showCloseLocations()">Show Locations In Radius</button>
<div id="map_canvas" style="width:500px; height:300px;">
</body>
</html>