Google Maps Api v3 - ค้นหาเครื่องหมายที่ใกล้ที่สุด


89

เมื่อฉันคลิกบนแผนที่วิธีใดจะเป็นวิธีที่ดีที่สุดในการค้นหาเครื่องหมายหรือเครื่องหมายที่ใกล้ที่สุด มีฟังก์ชั่นบางอย่างใน api ที่จะช่วยฉันทำเช่นนั้นหรือไม่?

มันคือ google map api v3


1
คุณใช้ฐานข้อมูลใดในการจัดเก็บ coords ของเครื่องหมายหรือไม่?
Argiropoulos Stavros

แน่นอนว่าตำแหน่งเครื่องหมายจะถูกเก็บไว้ในฐานข้อมูล mysql
user198003

คำตอบ:


113

ก่อนอื่นคุณต้องเพิ่ม eventlistener

google.maps.event.addListener(map, 'click', find_closest_marker);

จากนั้นสร้างฟังก์ชันที่วนรอบอาร์เรย์ของเครื่องหมายและใช้สูตร haversineเพื่อคำนวณระยะห่างของเครื่องหมายแต่ละตัวจากการคลิก

function rad(x) {return x*Math.PI/180;}
function find_closest_marker( event ) {
    var lat = event.latLng.lat();
    var lng = event.latLng.lng();
    var R = 6371; // radius of earth in km
    var distances = [];
    var closest = -1;
    for( i=0;i<map.markers.length; i++ ) {
        var mlat = map.markers[i].position.lat();
        var mlng = map.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;
        }
    }

    alert(map.markers[closest].title);
}

ซึ่งจะติดตามเครื่องหมายที่ใกล้เคียงที่สุดและแจ้งเตือนชื่อ

ฉันมีเครื่องหมายเป็นอาร์เรย์บนวัตถุแผนที่ของฉัน


2
ไม่ใช่เพื่อเปิดเธรดเก่า แต่ฉันได้พยายามใช้สิ่งนี้แล้วและดูเหมือนว่าจะค้นหาไปทางทิศตะวันออกแทนที่จะค้นหาสิ่งที่ใกล้เคียงที่สุด ดังนั้นถ้าฉันค้นหาตำแหน่งมันจะค้นหาไปทางทิศตะวันออกและหาทางที่ใกล้ที่สุดแม้ว่าจะมี REAL ปิดอยู่ทางตะวันตกก็ตาม มันสมเหตุสมผลไหม
LeeR

@ ลี - มันสมเหตุสมผล แต่ฉันไม่สามารถทำซ้ำปัญหาได้
Galen

1
ใช่สิ่งนี้ไม่ได้ผลเลยสำหรับฉัน - พาฉันไปที่แคลิฟอร์เนียของเราและฉันอยู่ที่นิวยอร์ก และมีเครื่องหมายที่ตำแหน่งของฉัน มันพบเครื่องหมายแม้ว่า!
mheavers

@mheavers - มีข้อผิดพลาดในรหัส เปลี่ยนจาก (i = 1 เป็นจาก (i = 0 ไม่รวมเครื่องหมายแรก
Galen

1
@Magico คุณไม่สามารถเปลี่ยนจาวาสคริปต์เป็นรหัส php ได้ คุณสามารถเขียน php wrapper ที่สร้างโค้ดจาวาสคริปต์เหมือนในคำตอบ ถ้าทำเองไม่ได้อย่าใช้ php เลย ...
Daniel W.


30

ฉันต้องการขยายคำแนะนำของ Leor สำหรับทุกคนที่สับสนเกี่ยวกับวิธีคำนวณตำแหน่งที่ใกล้ที่สุดและให้วิธีแก้ปัญหาที่ใช้งานได้จริง:

ฉันใช้เครื่องหมายในเช่นอาร์เรย์markersvar markers = [];

จากนั้นให้เรามีตำแหน่งเป็นอย่างเช่น var location = new google.maps.LatLng(51.99, -0.74);

จากนั้นเราก็ลดเครื่องหมายของเราเทียบกับตำแหน่งที่เรามีดังนี้:

markers.reduce(function (prev, curr) {

    var cpos = google.maps.geometry.spherical.computeDistanceBetween(location.position, curr.position);
    var ppos = google.maps.geometry.spherical.computeDistanceBetween(location.position, prev.position);

    return cpos < ppos ? curr : prev;

}).position

สิ่งที่ปรากฏคือLatLngวัตถุเครื่องหมายที่ใกล้เคียงที่สุดของคุณ


1
คำตอบสุดเจ๋ง!
Cesar Alonso

คำตอบเรียบร้อยและสะอาด!
TheeBen

สามารถใช้เพื่อจัดเรียงเครื่องหมายตามระยะทาง แต่กลับเพียงอันเดียวได้หรือไม่?
Louis W

แน่นอน @ หลุยส์ค้นหาวิธีการกรอง คุณสามารถใช้เพื่อจัดเรียงได้
โจนาธาน

1
ฉันทำให้มันทำงานได้โดยการลบตำแหน่งบนวัตถุตำแหน่ง ดังนี้: computeDistanceBetween (location, prev.position) ... เนื่องจากตำแหน่งเป็นวัตถุ LatLng อยู่แล้ว
holm50

9

สูตรข้างต้นไม่ได้ผลสำหรับฉัน แต่ฉันใช้สิ่งนี้โดยไม่มีปัญหาใด ๆ ส่งตำแหน่งปัจจุบันของคุณไปยังฟังก์ชันและวนผ่านอาร์เรย์ของเครื่องหมายเพื่อค้นหาตำแหน่งที่ใกล้เคียงที่สุด:

function find_closest_marker( lat1, lon1 ) {    
    var pi = Math.PI;
    var R = 6371; //equatorial radius
    var distances = [];
    var closest = -1;

    for( i=0;i<markers.length; i++ ) {  
        var lat2 = markers[i].position.lat();
        var lon2 = markers[i].position.lng();

        var chLat = lat2-lat1;
        var chLon = lon2-lon1;

        var dLat = chLat*(pi/180);
        var dLon = chLon*(pi/180);

        var rLat1 = lat1*(pi/180);
        var rLat2 = lat2*(pi/180);

        var a = Math.sin(dLat/2) * Math.sin(dLat/2) + 
                    Math.sin(dLon/2) * Math.sin(dLon/2) * Math.cos(rLat1) * Math.cos(rLat2); 
        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;
        }
    }

    // (debug) The closest marker is:
    console.log(markers[closest]);
}

1
คุณเติมmarkersอาร์เรย์ได้อย่างไร? เป็นโดยการสร้างเครื่องหมายโดยใช้var marker1 = new google.maps.Marker({ ... })?
enchance

1
@enchance ฉันต้องทำสิ่งนี้: map.markers = map.markers || [];จากนั้นสำหรับแต่ละเครื่องหมายmap.markers.push(marker);
travis


4

นี่คือฟังก์ชั่นอื่นที่ใช้งานได้ดีสำหรับฉันคืนระยะทางเป็นกิโลเมตร

 function distance(lat1, lng1, lat2, lng2) {
        var radlat1 = Math.PI * lat1 / 180;
        var radlat2 = Math.PI * lat2 / 180;
        var radlon1 = Math.PI * lng1 / 180;
        var radlon2 = Math.PI * lng2 / 180;
        var theta = lng1 - lng2;
        var radtheta = Math.PI * theta / 180;
        var dist = Math.sin(radlat1) * Math.sin(radlat2) + Math.cos(radlat1) * Math.cos(radlat2) * Math.cos(radtheta);
        dist = Math.acos(dist);
        dist = dist * 180 / Math.PI;
        dist = dist * 60 * 1.1515;

        //Get in in kilometers
        dist = dist * 1.609344;

        return dist;
    }

3

ใช้เมธอด computeDistanceBetween () Google map APIเพื่อคำนวณเครื่องหมายใกล้ระหว่างตำแหน่งของคุณและรายการเครื่องหมายบนแผนที่ Google

ขั้นตอน: -

  1. สร้างเครื่องหมายบนแผนที่ Google
    function addMarker(location) { var marker = new google.maps.Marker({ title: 'User added marker', icon: { path: google.maps.SymbolPath.BACKWARD_CLOSED_ARROW, scale: 5 }, position: location, map: map }); }

  2. เมื่อคลิกเมาส์สร้างเหตุการณ์สำหรับการหา lat ตามยาวของตำแหน่งของคุณแล้วส่งต่อไปยัง find_closest_marker ()

    function find_closest_marker(event) {
          var distances = [];
          var closest = -1;
          for (i = 0; i < markers.length; i++) {
            var d = google.maps.geometry.spherical.computeDistanceBetween(markers[i].position, event.latLng);
            distances[i] = d;
            if (closest == -1 || d < distances[closest]) {
              closest = i;
            }
          }
          alert('Closest marker is: ' + markers[closest].getTitle());
        }
    

เยี่ยมชมลิงค์นี้ตามขั้นตอน คุณจะได้รับเครื่องหมายใกล้ตำแหน่งของคุณมากขึ้น

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.