Google Maps API V3 - เครื่องหมายหลายตัวในจุดเดียวกัน


115

บิตติดอยู่ที่นี่ ฉันกำลังเรียกข้อมูลรายการ geo coords ผ่าน JSON และวางลงบนแผนที่ Google ทั้งหมดทำงานได้ดียกเว้นในกรณีที่ฉันมีเครื่องหมายสองตัวขึ้นไปในจุดเดียวกัน API จะแสดงเครื่องหมาย 1 ตัวเท่านั้นซึ่งเป็นเครื่องหมายบนสุด นี่ก็ยุติธรรมเพียงพอที่ฉันคิดว่า แต่ต้องการหาวิธีแสดงให้เห็นทั้งหมด

ฉันค้นหา google และพบวิธีแก้ปัญหาเล็กน้อย แต่ส่วนใหญ่ดูเหมือนจะเป็น V2 ของ API หรือไม่ได้ดีแค่นั้น ตามหลักการแล้วฉันต้องการโซลูชันที่คุณคลิกเครื่องหมายกลุ่มบางประเภทจากนั้นจะแสดงเครื่องหมายที่คลัสเตอร์รอบ ๆ จุดที่พวกเขาอยู่

ใครมีปัญหานี้หรือคล้ายกันและต้องการแบ่งปันวิธีแก้ปัญหา?

คำตอบ:


116

ลองดูที่OverlappingMarkerSpiderfier
มีหน้าสาธิต แต่ไม่แสดงเครื่องหมายที่อยู่ในจุดเดียวกันเป๊ะ ๆ มีเพียงบางหน้าเท่านั้นที่อยู่ใกล้กันมาก

แต่ตัวอย่างชีวิตจริงที่มีเครื่องหมายในจุดเดียวกันสามารถดูได้ที่http://www.ejw.de/ejw-vor-ort/ (เลื่อนลงเพื่อดูแผนที่และคลิกที่เครื่องหมายสองสามตัวเพื่อดูผลแมงมุม )

นั่นดูเหมือนจะเป็นทางออกที่สมบูรณ์แบบสำหรับปัญหาของคุณ


สิ่งนี้ยอดเยี่ยมและตรงตามความต้องการที่เหลือจากไลบรารีคลัสเตอร์ซึ่งไม่จัดการกับเครื่องหมายที่มี lat / long ที่แน่นอนเหมือนกัน
จัสติน

หากใช้OverlappingMarkerSpiderfierร่วมกับMarkerClustererตัวเลือกที่ดีคือการตั้งค่าmaxZoomตัวเลือกบนตัวสร้างคลัสเตอร์ "แยกกลุ่ม" เครื่องหมายนี้ไว้หลังระดับการซูมที่ระบุ
Diederik

@Tad ฉันไม่ทราบว่าคุณเป็นผู้พัฒนาเว็บไซต์นั้นหรือไม่ แต่ฉันต้องการแจ้งให้คุณทราบว่าแผนที่บน ejw.de เสีย ฉันได้รับข้อผิดพลาด JS
Alex

ฉันตรวจสอบการสาธิตที่เสนอแล้ว แต่ดูเหมือนว่าจะตายแล้ว หลังจากการวิจัยเพิ่มเติมฉันพบตัวอย่างนี้เกี่ยวกับวิธีการรวมคลัสเตอร์เครื่องหมายและ Spiderifier ไม่มีการสาธิตสด แต่เพียงแค่โคลนและทำตาม readme github.com/yagoferrer/markerclusterer-plus-spiderfier-example
Sax

34

การหักล้างเครื่องหมายไม่ใช่วิธีแก้ปัญหาที่แท้จริงหากตั้งอยู่ในอาคารเดียวกัน สิ่งที่คุณอาจต้องทำคือแก้ไข markerclusterer.js ดังนี้:

  1. เพิ่มวิธีการคลิกต้นแบบในคลาส MarkerClusterer เช่นนี้ - เราจะแทนที่สิ่งนี้ในภายหลังในฟังก์ชัน initialize () แผนที่:

    MarkerClusterer.prototype.onClick = function() { 
        return true; 
    };
    
  2. ในคลาส ClusterIcon ให้เพิ่มรหัสต่อไปนี้หลังจากทริกเกอร์คลัสเตอร์คลิก:

    // Trigger the clusterclick event.
    google.maps.event.trigger(markerClusterer, 'clusterclick', this.cluster_);
    
    var zoom = this.map_.getZoom();
    var maxZoom = markerClusterer.getMaxZoom();
    // if we have reached the maxZoom and there is more than 1 marker in this cluster
    // use our onClick method to popup a list of options
    if (zoom >= maxZoom && this.cluster_.markers_.length > 1) {
       return markerClusterer.onClickZoom(this);
    }
    
  3. จากนั้นในฟังก์ชัน initialize () ที่คุณเริ่มต้นแผนที่และประกาศวัตถุ MarkerClusterer ของคุณ:

    markerCluster = new MarkerClusterer(map, markers);
    // onClickZoom OVERRIDE
    markerCluster.onClickZoom = function() { return multiChoice(markerCluster); }
    

    โดยที่ multiChoice () คือฟังก์ชันของคุณ (ยังไม่ต้องเขียน) เพื่อป๊อปอัป InfoWindow พร้อมรายการตัวเลือกให้เลือก สังเกตว่าวัตถุ markerClusterer ถูกส่งไปยังฟังก์ชันของคุณเนื่องจากคุณจะต้องใช้สิ่งนี้เพื่อกำหนดจำนวนเครื่องหมายในคลัสเตอร์นั้น ตัวอย่างเช่น:

    function multiChoice(mc) {
         var cluster = mc.clusters_;
         // if more than 1 point shares the same lat/long
         // the size of the cluster array will be 1 AND
         // the number of markers in the cluster will be > 1
         // REMEMBER: maxZoom was already reached and we can't zoom in anymore
         if (cluster.length == 1 && cluster[0].markers_.length > 1)
         {
              var markers = cluster[0].markers_;
              for (var i=0; i < markers.length; i++)
              {
                  // you'll probably want to generate your list of options here...
              }
    
              return false;
         }
    
         return true;
    }
    

17

ฉันใช้สิ่งนี้ควบคู่ไปกับ jQuery และทำงานได้:

var map;
var markers = [];
var infoWindow;

function initialize() {
    var center = new google.maps.LatLng(-29.6833300, 152.9333300);

    var mapOptions = {
        zoom: 5,
        center: center,
        panControl: false,
        zoomControl: false,
        mapTypeControl: false,
        scaleControl: false,
        streetViewControl: false,
        overviewMapControl: false,
        mapTypeId: google.maps.MapTypeId.ROADMAP
      }


    map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);

    $.getJSON('jsonbackend.php', function(data) {
        infoWindow = new google.maps.InfoWindow();

        $.each(data, function(key, val) {
            if(val['LATITUDE']!='' && val['LONGITUDE']!='')
            {                
                // Set the coordonates of the new point
                var latLng = new google.maps.LatLng(val['LATITUDE'],val['LONGITUDE']);

                //Check Markers array for duplicate position and offset a little
                if(markers.length != 0) {
                    for (i=0; i < markers.length; i++) {
                        var existingMarker = markers[i];
                        var pos = existingMarker.getPosition();
                        if (latLng.equals(pos)) {
                            var a = 360.0 / markers.length;
                            var newLat = pos.lat() + -.00004 * Math.cos((+a*i) / 180 * Math.PI);  //x
                            var newLng = pos.lng() + -.00004 * Math.sin((+a*i) / 180 * Math.PI);  //Y
                            var latLng = new google.maps.LatLng(newLat,newLng);
                        }
                    }
                }

                // Initialize the new marker
                var marker = new google.maps.Marker({map: map, position: latLng, title: val['TITLE']});

                // The HTML that is shown in the window of each item (when the icon it's clicked)
                var html = "<div id='iwcontent'><h3>"+val['TITLE']+"</h3>"+
                "<strong>Address: </strong>"+val['ADDRESS']+", "+val['SUBURB']+", "+val['STATE']+", "+val['POSTCODE']+"<br>"+
                "</div>";

                // Binds the infoWindow to the point
                bindInfoWindow(marker, map, infoWindow, html);

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

        // Make a cluster with the markers from the array
        var markerCluster = new MarkerClusterer(map, markers, { zoomOnClick: true, maxZoom: 15, gridSize: 20 });
    });
}

function markerOpen(markerid) {
    map.setZoom(22);
    map.panTo(markers[markerid].getPosition());
    google.maps.event.trigger(markers[markerid],'click');
    switchView('map');
}

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

Thx ทำงานได้อย่างสมบูรณ์แบบสำหรับฉัน :) สิ่งที่ฉันค้นหาตั้งแต่ชั่วโมง: p
Jicao

โซลูชันที่สวยงามและสง่างาม ขอบคุณ!
Concept211

โซลูชันที่สมบูรณ์แบบชดเชยเล็กน้อย! เป็นไปได้หรือไม่ที่เราวางเมาส์เหนือเครื่องหมายและกว่าจะแสดงเครื่องหมายหลายตัว
Intekhab Khan

14

เมื่อขยายคำตอบของ Chaoleyฉันใช้ฟังก์ชันที่ให้รายการสถานที่ (วัตถุที่มีlngและlatคุณสมบัติ) ที่มีพิกัดเหมือนกันทุกประการย้ายพวกเขาออกจากตำแหน่งเดิมเล็กน้อย (การปรับเปลี่ยนวัตถุในสถานที่) จากนั้นพวกเขาจะสร้างวงกลมที่สวยงามรอบ ๆ จุดศูนย์กลาง

ฉันพบว่าสำหรับละติจูด (52deg เหนือ) ของฉันรัศมีวงกลม 0.0003 องศาทำงานได้ดีที่สุดและคุณต้องชดเชยความแตกต่างระหว่างองศาละติจูดและลองจิจูดเมื่อแปลงเป็นกิโลเมตร คุณสามารถค้นหาแปลงประมาณสำหรับเส้นของคุณที่นี่

var correctLocList = function (loclist) {
    var lng_radius = 0.0003,         // degrees of longitude separation
        lat_to_lng = 111.23 / 71.7,  // lat to long proportion in Warsaw
        angle = 0.5,                 // starting angle, in radians
        loclen = loclist.length,
        step = 2 * Math.PI / loclen,
        i,
        loc,
        lat_radius = lng_radius / lat_to_lng;
    for (i = 0; i < loclen; ++i) {
        loc = loclist[i];
        loc.lng = loc.lng + (Math.cos(angle) * lng_radius);
        loc.lat = loc.lat + (Math.sin(angle) * lat_radius);
        angle += step;
    }
};

1
DzinX ฉันใช้เวลา 4 ชั่วโมงที่ผ่านมาในการพยายามคิดว่าจะนำโค้ดของคุณไปใช้ในโค้ดของฉันได้อย่างไรโดยไม่มีประโยชน์ ฉันได้ข้อสรุปว่าฉันดูดสิ่งนี้และขอขอบคุณสำหรับความช่วยเหลือของคุณ นี่คือที่ที่ฉันพยายามเสียบรหัส: pastebin.com/5qYbvybm - ขอความช่วยเหลือใด ๆ ! ขอบคุณ!
WebMW

WebMW: หลังจากที่คุณแยกเครื่องหมายออกจาก XML ก่อนอื่นคุณต้องจัดกลุ่มเครื่องหมายเหล่านี้เป็นรายการเพื่อให้แต่ละรายการมีเครื่องหมายที่ชี้ไปยังตำแหน่งเดียวกันทั้งหมด จากนั้นในแต่ละรายการที่มีองค์ประกอบมากกว่าหนึ่งรายการให้เรียกใช้ correctLocList () หลังจากทำเสร็จแล้วให้สร้างวัตถุ google.maps.Marker
DzinX

มันไม่ทำงาน .... มันแค่เปลี่ยน lat longs ของฉันจาก 37.68625400000000000,-75.71669800000000000เป็น 37.686254,-75.716698ซึ่งก็เหมือนกันสำหรับทุกค่า ... M คาดหวังบางอย่างเช่น ... 37.68625400000000000,-75.71669800000000000เป็น 37.6862540000001234,-75.7166980000001234 37.6862540000005678,-75.7166980000005678.. ฯลฯ ฉันก็ลองเปลี่ยนมุมมอง
เปรมชนกทิวา

อืมลองขุดดูสักหน่อยและหวังว่า @DzinX ยังอยู่ในพื้นที่ คุณสามารถหาคู่ (หรือใครก็ได้) อธิบายว่าคุณได้รับตัวเลขเหล่านั้นมาได้อย่างไร? Lng_radius ฯลฯ ? ขอบคุณมาก. :)
Vae

1
@Vae: รัศมีคือขนาดที่คุณต้องการให้วงกลมมีขนาดใหญ่ คุณต้องการให้วงกลมดูกลมเป็นพิกเซลดังนั้นคุณต้องทราบว่าในตำแหน่งของคุณสัดส่วนของละติจูด 1 องศาถึงลองจิจูด 1 องศา (เป็นพิกเซลบนแผนที่) คุณสามารถค้นหาสิ่งนี้ได้ในบางเว็บไซต์หรือทดลองจนกว่าจะได้หมายเลขที่ถูกต้อง มุมคือเท่าใดพินแรกที่อยู่ทางขวาจากด้านบน
DzinX

11

@Ignatius คำตอบที่ยอดเยี่ยมที่สุดอัปเดตเพื่อทำงานกับ v2.0.7 ของ MarkerClustererPlus

  1. เพิ่มวิธีการคลิกต้นแบบในคลาส MarkerClusterer เช่นนี้ - เราจะแทนที่สิ่งนี้ในภายหลังในฟังก์ชัน initialize () แผนที่:

    // BEGIN MODIFICATION (around line 715)
    MarkerClusterer.prototype.onClick = function() { 
        return true; 
    };
    // END MODIFICATION
    
  2. ในคลาส ClusterIcon ให้เพิ่มโค้ดต่อไปนี้หลังจากทริกเกอร์ click / clusterclick:

    // EXISTING CODE (around line 143)
    google.maps.event.trigger(mc, "click", cClusterIcon.cluster_);
    google.maps.event.trigger(mc, "clusterclick", cClusterIcon.cluster_); // deprecated name
    
    // BEGIN MODIFICATION
    var zoom = mc.getMap().getZoom();
    // Trying to pull this dynamically made the more zoomed in clusters not render
    // when then kind of made this useless. -NNC @ BNB
    // var maxZoom = mc.getMaxZoom();
    var maxZoom = 15;
    // if we have reached the maxZoom and there is more than 1 marker in this cluster
    // use our onClick method to popup a list of options
    if (zoom >= maxZoom && cClusterIcon.cluster_.markers_.length > 1) {
        return mc.onClick(cClusterIcon);
    }
    // END MODIFICATION
    
  3. จากนั้นในฟังก์ชัน initialize () ที่คุณเริ่มต้นแผนที่และประกาศวัตถุ MarkerClusterer ของคุณ:

    markerCluster = new MarkerClusterer(map, markers);
    // onClick OVERRIDE
    markerCluster.onClick = function(clickedClusterIcon) { 
      return multiChoice(clickedClusterIcon.cluster_); 
    }

    โดยที่ multiChoice () คือฟังก์ชันของคุณ (ยังไม่ต้องเขียน) เพื่อป๊อปอัป InfoWindow พร้อมรายการตัวเลือกให้เลือก สังเกตว่าวัตถุ markerClusterer ถูกส่งไปยังฟังก์ชันของคุณเนื่องจากคุณจะต้องใช้สิ่งนี้เพื่อกำหนดจำนวนเครื่องหมายในคลัสเตอร์นั้น ตัวอย่างเช่น:

    function multiChoice(clickedCluster) {
      if (clickedCluster.getMarkers().length > 1)
      {
        // var markers = clickedCluster.getMarkers();
        // do something creative!
        return false;
      }
      return true;
    };

1
ขอบคุณมันทำงานได้อย่างสมบูรณ์แบบ! สำหรับmaxZoomปัญหาของคุณฉันคิดว่านี่เป็นปัญหาเฉพาะในกรณีที่ไม่มีการตั้งค่า maxZoom หรือ maxZoom สำหรับคลัสเตอร์มากกว่าการซูมสำหรับแผนที่ ฉันได้แทนที่ฮาร์ดโค้ดของคุณด้วยตัวอย่างข้อมูลนี้และดูเหมือนว่าจะใช้งานได้ดี:var maxZoom = mc.getMaxZoom(); if (null === maxZoom || maxZoom > mc.getMap().maxZoom) { maxZoom = mc.getMap().maxZoom; if (null === maxZoom) { maxZoom = 15; } }
Pascal

ฉันรู้ว่านี่เก่าจริงๆ แต่ฉันพยายามใช้วิธีนี้ ฉันใช้งานได้ แต่ในกรณีของการแสดงหน้าต่างข้อมูลพร้อมข้อมูลคลัสเตอร์ ... ฉันจะหาตำแหน่งเครื่องหมายของคลัสเตอร์ที่คลิกในตอนแรกได้อย่างไรเพื่อให้ฉันสามารถแสดงหน้าต่างข้อมูลได้ markers คืออาร์เรย์ข้อมูลของฉัน ... แต่ฉันจะแสดงหน้าต่างข้อมูลบนไอคอนคลัสเตอร์ / เครื่องหมายได้อย่างไร
user756659

@ user756659 ใน multiChoice คุณได้รับ lat / lng ผ่าน: clickedCluster.center_.lat()/clickedCluster.center_.lng()
Jens Kohl

1
@Pascal และด้วยความสับสนเล็กน้อยเราจบลงด้วยสิ่งนี้ซึ่งสามารถใช้งานได้ แต่อย่างที่เทาของหลามพูด "จำนวนความสามารถในการอ่าน" var maxZoom = Math.min (mc.getMaxZoom () || 15, mc.getMap (). maxZoom || 15);
Nande

6

คำตอบข้างบนนั้นดูหรูหรากว่า แต่ฉันพบวิธีที่รวดเร็วและสกปรกซึ่งใช้งานได้ดีอย่างเหลือเชื่อจริงๆ คุณสามารถดูการใช้งานจริงได้ที่www.buildinglit.com

สิ่งที่ฉันทำคือเพิ่มค่าออฟเซ็ตแบบสุ่มให้กับละติจูดและลองจิจูดในหน้า genxml.php ของฉันดังนั้นมันจึงให้ผลลัพธ์ที่แตกต่างกันเล็กน้อยในแต่ละครั้งโดยมีการชดเชยทุกครั้งที่สร้างแผนที่ด้วยเครื่องหมาย ฟังดูเหมือนแฮ็ค แต่ในความเป็นจริงคุณเพียงแค่ต้องใช้เครื่องหมายเพื่อขยับเขยิบเล็กน้อยในทิศทางแบบสุ่มเพื่อให้คลิกได้บนแผนที่หากซ้อนทับกัน มันใช้งานได้ดีจริง ๆ ฉันจะบอกว่าดีกว่าวิธีแมงมุมเพราะใครก็ตามที่ต้องการจัดการกับความซับซ้อนนั้นและให้พวกมันผุดขึ้นทุกที่ คุณเพียงแค่ต้องการให้สามารถเลือกเครื่องหมาย การสะกิดแบบสุ่มจะทำงานได้อย่างสมบูรณ์แบบ

นี่คือตัวอย่างของการสร้างโหนดการวนซ้ำคำสั่ง while ใน php_genxml.php ของฉัน

while ($row = @mysql_fetch_assoc($result)){ $offset = rand(0,1000)/10000000;
$offset2 = rand(0, 1000)/10000000;
$node = $dom->createElement("marker");
$newnode = $parnode->appendChild($node);
$newnode->setAttribute("name", $row['name']);
$newnode->setAttribute("address", $row['address']);
$newnode->setAttribute("lat", $row['lat'] + $offset);
$newnode->setAttribute("lng", $row['lng'] + $offset2);
$newnode->setAttribute("distance", $row['distance']);
$newnode->setAttribute("type", $row['type']);
$newnode->setAttribute("date", $row['date']);
$newnode->setAttribute("service", $row['service']);
$newnode->setAttribute("cost", $row['cost']);
$newnode->setAttribute("company", $company);

สังเกตใต้ lat และ long จะมีเครื่องหมาย + offset จาก 2 ตัวแปรข้างต้น ฉันต้องหารสุ่มด้วย 0,1000 คูณ 10,000000 เพื่อให้ได้ทศนิยมที่สุ่มเล็กพอที่จะขยับเครื่องหมายไปมาแทบไม่ได้ อย่าลังเลที่จะปรับแต่งตัวแปรนั้นเพื่อให้ได้ตัวแปรที่ตรงกับความต้องการของคุณมากขึ้น


เย็น! นี่คือแฮ็คสกปรกที่ฉันพบว่ามีประโยชน์มากไม่จำเป็นต้องยุ่งกับรหัส api ของ Google Maps
CuongDC

3

สำหรับสถานการณ์ที่มีบริการหลายอย่างในอาคารเดียวกันคุณสามารถหักล้างเครื่องหมายเพียงเล็กน้อย (พูดด้วย. 001 องศา) ในรัศมีจากจุดจริง สิ่งนี้ควรให้เอฟเฟกต์ภาพที่ดีด้วย


3

นี่เป็นวิธีแก้ปัญหา 'รวดเร็วและสกปรก' ที่หยุดชะงักคล้ายกับที่ Matthew Fox แนะนำคราวนี้ใช้ JavaScript

ใน JavaScript คุณสามารถชดเชย lat และ long ของตำแหน่งทั้งหมดของคุณได้โดยการเพิ่มค่าชดเชยแบบสุ่มเล็ก ๆ ให้กับทั้งสองเช่น

myLocation[i].Latitude+ = (Math.random() / 25000)

(ฉันพบว่าการหารด้วย25,000จะให้การแยกที่เพียงพอ แต่ไม่ได้เคลื่อนเครื่องหมายอย่างมากจากตำแหน่งที่แน่นอนเช่นที่อยู่เฉพาะ)

สิ่งนี้ทำให้การหักล้างกันได้ดีพอสมควร แต่หลังจากที่คุณซูมเข้าใกล้ ๆ เท่านั้น เมื่อซูมออกจะยังไม่ชัดเจนว่ามีหลายตัวเลือกสำหรับสถานที่


1
ฉันชอบสิ่งนี้. หากคุณไม่ต้องการเครื่องหมายตัวแทนที่ถูกต้องเพียงแค่ลด 25000 เป็น 250 หรือ 25 วิธีแก้ปัญหาที่ง่ายและรวดเร็ว
Fid

2

ตรวจสอบMarker Clustererสำหรับ V3 - ไลบรารีนี้รวมจุดใกล้เคียงไว้ในเครื่องหมายกลุ่ม แผนที่จะซูมเข้าเมื่อคลิกคลัสเตอร์ ฉันคิดว่าเมื่อซูมเข้าคุณจะยังคงมีปัญหาเดียวกันกับเครื่องหมายในจุดเดียวกัน


ใช่ลองดูห้องสมุดเล็ก ๆ ที่มีประโยชน์ แต่ดูเหมือนว่าจะไม่สามารถเอาชนะปัญหาได้ ฉันกำลังสร้างตัวระบุตำแหน่งบริการสำหรับ บริษัท ที่บางครั้งมีบริการมากกว่าหนึ่งบริการในกลุ่มสำนักงานเดียวกันและด้วยเหตุนี้จึงมี coords ทางภูมิศาสตร์เดียวกัน ฉันสามารถแสดงบริการต่างๆในหน้าต่างข้อมูลเดียว แต่ดูเหมือนจะไม่ใช่วิธีที่ดีที่สุด ...
Louzoid

@Louzoid Marker Clusterer ไม่สามารถเอาชนะปัญหาได้อย่างที่ฉันเพิ่งค้นพบ ฉันประสบปัญหาเดียวกันฉันมีหลาย บริษัท ภายในอาคารเดียวดังนั้นจึงแสดงเครื่องหมายเพียง 1 ตัว
Rob

1

อัปเดตให้ทำงานกับ MarkerClustererPlus

  google.maps.event.trigger(mc, "click", cClusterIcon.cluster_);
  google.maps.event.trigger(mc, "clusterclick", cClusterIcon.cluster_); // deprecated name

  // BEGIN MODIFICATION
  var zoom = mc.getMap().getZoom();
  // Trying to pull this dynamically made the more zoomed in clusters not render
  // when then kind of made this useless. -NNC @ BNB
  // var maxZoom = mc.getMaxZoom();
  var maxZoom = 15;
  // if we have reached the maxZoom and there is more than 1 marker in this cluster
  // use our onClick method to popup a list of options
  if (zoom >= maxZoom && cClusterIcon.cluster_.markers_.length > 1) {
    var markers = cClusterIcon.cluster_.markers_;
    var a = 360.0 / markers.length;
    for (var i=0; i < markers.length; i++)
    {
        var pos = markers[i].getPosition();
        var newLat = pos.lat() + -.00004 * Math.cos((+a*i) / 180 * Math.PI);  // x
        var newLng = pos.lng() + -.00004 * Math.sin((+a*i) / 180 * Math.PI);  // Y
        var finalLatLng = new google.maps.LatLng(newLat,newLng);
        markers[i].setPosition(finalLatLng);
        markers[i].setMap(cClusterIcon.cluster_.map_);
    }
    cClusterIcon.hide();
    return ;
  }
  // END MODIFICATION

วิธีนี้กำหนดให้ผู้ใช้คลิกไอคอนคลัสเตอร์และจะไม่ครอบคลุมกรณีการใช้งานที่การนำทางทำได้ด้วยแถบเลื่อนซูมหรือการเลื่อนเมาส์ มีความคิดอย่างไรในการแก้ไขปัญหาเหล่านั้น?
Remi Sture

1

ฉันชอบวิธีแก้ปัญหาง่ายๆนี่คือของฉัน แทนที่จะแก้ไข lib ซึ่งจะทำให้ยากต่อการติดตั้ง คุณสามารถดูเหตุการณ์เช่นนี้ได้

google.maps.event.addListener(mc, "clusterclick", onClusterClick);

จากนั้นคุณสามารถจัดการได้

function onClusterClick(cluster){
    var ms = cluster.getMarkers();

ฉันคือใช้ bootstrap เพื่อแสดงแผงที่มีรายการ ซึ่งฉันพบว่าสะดวกสบายและใช้งานได้ดีกว่าการกินแมงมุมในสถานที่ที่ "แออัด" (หากคุณกำลังใช้คลัสเตอร์โอกาสที่คุณจะจบลงด้วยการชนกันเมื่อคุณแมงมุม) คุณสามารถตรวจสอบการซูมได้เช่นกัน

BTW ฉันเพิ่งพบแผ่นพับและดูเหมือนว่าจะทำงานได้ดีขึ้นมากคลัสเตอร์ AND spiderfy ทำงานได้อย่างลื่นไหลมากhttp://leaflet.github.io/Leaflet.markercluster/example/marker-clustering-realworld.10000.html และเป็นโอเพ่นซอร์ส


0

ตรวจสอบสิ่งนี้: https://github.com/plank/MarkerClusterer

นี่คือ MarkerCluster ที่แก้ไขให้มี infoWindow ในเครื่องหมายคลัสเตอร์เมื่อคุณมีเครื่องหมายหลายตัวในตำแหน่งเดียวกัน

คุณสามารถดูวิธีการทำงานได้ที่นี่: http://culturedays.ca/en/2013-activities


0

ขยายคำตอบที่ให้ไว้ข้างต้นเพียงตรวจสอบให้แน่ใจว่าคุณได้ตั้งค่าตัวเลือก maxZoom เมื่อเริ่มต้นวัตถุแผนที่


0

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

// This code is in swift
for loop markers
{
//create marker
let mapMarker = GMSMarker()
mapMarker.groundAnchor = CGPosition(0.5, 0.5)
mapMarker.position = //set the CLLocation
//instead of setting marker.icon set the iconView
let image:UIIMage = UIIMage:init(named:"filename")
let imageView:UIImageView = UIImageView.init(frame:rect(0,0, ((image.width/2 * markerIndex) + image.width), image.height))
imageView.contentMode = .Right
imageView.image = image
mapMarker.iconView = imageView
mapMarker.map = mapView
}

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


0

จะหนีไปได้อย่างไร .. [Swift]

    var clusterArray = [String]()
    var pinOffSet : Double = 0
    var pinLat = yourLat
    var pinLong = yourLong
    var location = pinLat + pinLong

กำลังจะสร้างเครื่องหมายใหม่? ตรวจสอบclusterArrayและจัดการมันชดเชย

 if(!clusterArray.contains(location)){
        clusterArray.append(location)
    } else {

        pinOffSet += 1
        let offWithIt = 0.00025 // reasonable offset with zoomLvl(14-16)
        switch pinOffSet {
        case 1 : pinLong = pinLong + offWithIt ; pinLat = pinLat + offWithIt
        case 2 : pinLong = pinLong + offWithIt ; pinLat = pinLat - offWithIt
        case 3 : pinLong = pinLong - offWithIt ; pinLat = pinLat - offWithIt
        case 4 : pinLong = pinLong - offWithIt ; pinLat = pinLat + offWithIt
        default : print(1)
        }


    }

ผลลัพธ์

ใส่คำอธิบายภาพที่นี่


0

การเพิ่มคำตอบอัจฉริยะส่อเสียดของ Matthew Fox ฉันได้เพิ่มการชดเชยแบบสุ่มเล็ก ๆ ให้กับ lat และ lng แต่ละอันเมื่อตั้งค่าวัตถุเครื่องหมาย ตัวอย่างเช่น:

new LatLng(getLat()+getMarkerOffset(), getLng()+getMarkerOffset()),

private static double getMarkerOffset(){
    //add tiny random offset to keep markers from dropping on top of themselves
    double offset =Math.random()/4000;
    boolean isEven = ((int)(offset *400000)) %2 ==0;
    if (isEven) return  offset;
    else        return -offset;
}

-2

การขยายคำตอบด้านบนเมื่อคุณเข้าร่วมสตริงแล้วไม่ได้เพิ่ม / ลบตำแหน่ง (เช่น "37.12340-0.00069") ให้แปลงละติจูด / ลองจิจูดเดิมของคุณเป็นลอยเช่นใช้ parseFloat () จากนั้นเพิ่มหรือลบการแก้ไข

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