Znaczniki Google pod tym samym adresem nie pokazują wszystkich znaczników

16

Pracowałem nad tą mapą - http://www.mediwales.com/mapping/test/

Wypisuje firmy dobrze i grupuje je w porządku, ale pojawił się problem z firmami w tym samym budynku o tym samym adresie. Pokazuje tylko jedną firmę, a nie wszystkie.

Jak mogę uzyskać wyświetlanie wszystkich firm pod tym samym adresem?

Znaczniki są geokodowane według nazwy / numeru budynku, ulicy, miasta, kodu pocztowego. Zgaduję, że znaczniki są tam, ponieważ budynek, w którym 3 firmy pokazują 3 w klastrze. Ale kiedy klikniesz, wyświetli się tylko jedna firma.

AKTUALIZACJA:

Udało mi się zmusić je do przesunięcia, ale kompensuje wszystkie znaczniki, gdy chcę, aby były przesunięte tylko wtedy, gdy jest więcej niż jeden znacznik tego samego. (Dzięki odpowiedzi Casey).

   <script type="text/javascript">
    //<![CDATA[

    var customIcons = {
      restaurant: {
        icon: 'http://labs.google.com/ridefinder/images/mm_20_blue.png',
        shadow: 'http://labs.google.com/ridefinder/images/mm_20_shadow.png'
      },
      bar: {
        icon: 'http://labs.google.com/ridefinder/images/mm_20_red.png',
        shadow: 'http://labs.google.com/ridefinder/images/mm_20_shadow.png'
      }
    };

    function load() {
      var cluster = [];
      var map = new google.maps.Map(document.getElementById("map"), {
        center: new google.maps.LatLng(53.4788, -3.9551),
        zoom: 6,
        mapTypeId: 'roadmap'
      });
var infowindow = new google.maps.InfoWindow();
var min = .999999;
var max = 1.000001;

      // Change this depending on the name of your PHP file
      downloadUrl("<?php bloginfo('stylesheet_directory'); ?>/phpsqlajax_genxml.php ", function(data) {
        var xml = data.responseXML;
        var markers = xml.documentElement.getElementsByTagName("marker");
        for (var i = 0; i < markers.length; i++) {
          var name = markers[i].getAttribute("name");
          var address = markers[i].getAttribute("address");
          var type = markers[i].getAttribute("type");



          var offsetLat = markers[i].getAttribute("lat") * (Math.random() * (max - min) + min);
          var offsetLng = markers[i].getAttribute("lng") * (Math.random() * (max - min) + min);



          var point = new google.maps.LatLng(offsetLat, offsetLng);
          var html = "<b>" + name + "</b> <br/>" + address;
          var icon = customIcons[type] || {};
          var marker = new google.maps.Marker({
            map: map,
            position: point,
            icon: icon.icon,
            shadow: icon.shadow
          });
          google.maps.event.addListener(marker, 'click', (function(marker, i) {
                        return function() {
                            infowindow.setContent(markers[i].getAttribute("name"));
                            infowindow.open(map, marker);
                        }
                    })(marker, i));
          cluster.push(marker);
        }
        var mc = new MarkerClusterer(map,cluster);
      });
    }

    function bindInfoWindow(marker, map, infoWindow, html) {
      google.maps.event.addListener(marker, 'click', function() {
        infoWindow.setContent(html);
        infoWindow.open(map, marker);
      });
    }

    function downloadUrl(url, callback) {
      var request = window.ActiveXObject ?
          new ActiveXObject('Microsoft.XMLHTTP') :
          new XMLHttpRequest;

      request.onreadystatechange = function() {
        if (request.readyState == 4) {
          request.onreadystatechange = doNothing;
          callback(request, request.status);
        }
      };

      request.open('GET', url, true);
      request.send(null);
    }

    function doNothing() {}

    //]]>
  </script>

   <script type="text/javascript">
    //<![CDATA[

    var customIcons = {
      restaurant: {
        icon: 'http://labs.google.com/ridefinder/images/mm_20_blue.png',
        shadow: 'http://labs.google.com/ridefinder/images/mm_20_shadow.png'
      },
      bar: {
        icon: 'http://labs.google.com/ridefinder/images/mm_20_red.png',
        shadow: 'http://labs.google.com/ridefinder/images/mm_20_shadow.png'
      }
    };

    function load() {
      var cluster = [];
      var map = new google.maps.Map(document.getElementById("map"), {
        center: new google.maps.LatLng(53.4788, -3.9551),
        zoom: 6,
        mapTypeId: 'roadmap'
      });
var infowindow = new google.maps.InfoWindow();

      // Change this depending on the name of your PHP file
      downloadUrl("<?php bloginfo('stylesheet_directory'); ?>/phpsqlajax_genxml.php ", function(data) {
        var xml = data.responseXML;
        var markers = xml.documentElement.getElementsByTagName("marker");
        for (var i = 0; i < markers.length; i++) {
          var name = markers[i].getAttribute("name");
          var address = markers[i].getAttribute("address");
          var type = markers[i].getAttribute("type");
          var point = new google.maps.LatLng(
              parseFloat(markers[i].getAttribute("lat")),
              parseFloat(markers[i].getAttribute("lng")));
          var html = "<b>" + name + "</b> <br/>" + address;
          var icon = customIcons[type] || {};
          var marker = new google.maps.Marker({
            map: map,
            position: point,
            icon: icon.icon,
            shadow: icon.shadow
          });
          google.maps.event.addListener(marker, 'click', (function(marker, i) {
                        return function() {
                            infowindow.setContent(markers[i].getAttribute("name"));
                            infowindow.open(map, marker);
                        }
                    })(marker, i));
          cluster.push(marker);
        }
        var mc = new MarkerClusterer(map,cluster);
      });
    }

    function bindInfoWindow(marker, map, infoWindow, html) {
      google.maps.event.addListener(marker, 'click', function() {
        infoWindow.setContent(html);
        infoWindow.open(map, marker);
      });
    }

    function downloadUrl(url, callback) {
      var request = window.ActiveXObject ?
          new ActiveXObject('Microsoft.XMLHTTP') :
          new XMLHttpRequest;

      request.onreadystatechange = function() {
        if (request.readyState == 4) {
          request.onreadystatechange = doNothing;
          callback(request, request.status);
        }
      };

      request.open('GET', url, true);
      request.send(null);
    }

    function doNothing() {}

    //]]>
  </script>
Obrabować
źródło

Odpowiedzi:

15

Klaster wyświetla się poprawnie. Wszystkie znaczniki są drukowane. Problem polega na tym, że możesz kliknąć tylko najwyższy marker, przez co wygląda na to, że jest tylko jeden marker.

Aby zobaczyć zawartość znaczników zbieżnych, musisz przekazać zawartość okna informacyjnego leżących poniżej znaczników do najwyższego znacznika.

Aby to zrobić, po pierwsze, śledź każdy marker. Używasz MarkerClusterer, więc instancja markerClusterer będzie przechowywać każdy marker. Po powrocie każdego wyniku geokodu porównaj porównanie tego żądania ze wszystkimi wykreślonymi znacznikami. Możesz porównywać pozycje za pomocą metody równości z latlng obiektu.

Jeśli nowy znacznik odpowiada pozycji istniejącego znacznika, pobierz zawartość okna informacyjnego z pierwszego znacznika i dołącz go do zawartości okna nowego znacznika. W ten sposób kliknięcie najwyższego znacznika (drugiej firmy) spowoduje wyświetlenie informacji z obu firm. Jeśli istnieją więcej niż dwie firmy, musisz pobrać zawartość okna informacyjnego dla wszystkich pasujących znaczników. Ta metoda pozwoli również klasterowi markerów nadal wyświetlać prawidłową liczbę markerów.

Oto działający przykład i kod javascript. Pierwszy i drugi adres są takie same. Gdy klikniesz znacznik 2, wyświetli się „2 i 1”.

<script type="text/javascript"> 
var map;

//marker clusterer
var mc;
var mcOptions = {gridSize: 20, maxZoom: 17};

//global infowindow
var infowindow = new google.maps.InfoWindow();

//geocoder
var geocoder = new google.maps.Geocoder(); 

var address = new Array("1000 Market St, Philadelphia, PA","1000 Market St, Philadelphia, PA","1002 Market St, Philadelphia, PA","1004 Market St, Philadelphia, PA");
var content = new Array("1","2","3","4");

function createMarker(latlng,text) {

    var marker = new google.maps.Marker({
        position: latlng
    });

    ///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 currentMarker = allMarkers[i];
            var pos = currentMarker.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);
    });

    return marker;
}

function geocodeAddress(address,i) {

    geocoder.geocode( {'address': address}, function(results, status) {

        if (status == google.maps.GeocoderStatus.OK) {

            var marker = createMarker(results[0].geometry.location,content[i]);
            mc.addMarker(marker);

        } else { 
            alert("Geocode was not successful for the following reason: " + status); 
        } 
    });
}

function initialize(){

    var options = { 
        zoom: 13, 
        center: new google.maps.LatLng(39.96225,-75.13222), 
        mapTypeId: google.maps.MapTypeId.ROADMAP 
    }; 

    map = new google.maps.Map(document.getElementById('map'), options); 

    //marker cluster
    mc = new MarkerClusterer(map, [], mcOptions);

    for (i=0; i<address.length; i++) { 
        geocodeAddress(address[i],i);
    }

}       
</script> 

EDYCJA: Odpowiedź na komentarz

Alternatywnie, możesz przesuwać znaczniki zbieżności, stosując niewielki (na przykład liczbę losową między 0,999999 a 1,000001) mnożnik do pozycji każdego znacznika zbiegu okoliczności. Oto przykład. Wykorzystuje to te same dane, co w pierwszym przykładzie, z tym wyjątkiem, że zamiast znaczników 1 i 2 umieszczonych jeden nad drugim i dzielących okno informacyjne, znacznik 2 jest przesunięty względem znacznika 1. Uwaga: wyniki w geokodzie będą trochę mniej dokładne. Odpowiedni kod poniżej:

//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) {

        ///get array of markers currently in cluster
        var allMarkers = mc.getMarkers();

        //final position for marker, could be updated if another marker already exists in same position
        var finalLatLng = latlng;

        //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 a marker already exists in the same position as this marker
                if (latlng.equals(pos)) {

                    //update the position of the coincident marker by applying a small multipler to its coordinates
                    var newLat = latlng.lat() * (Math.random() * (max - min) + min);
                    var newLng = latlng.lng() * (Math.random() * (max - min) + min);

                    finalLatLng = new google.maps.LatLng(newLat,newLng);

                }                   
            }
        }

        var marker = new google.maps.Marker({
            position: finalLatLng
        });     

        google.maps.event.addListener(marker, 'click', function() {
            infowindow.close();
            infowindow.setContent(text);
            infowindow.open(map,marker);
        });

        return marker;
    }
Casey
źródło
Dziękuję za odpowiedź. Właśnie wracam do tego projektu! Zgadza się, czy można odrobinę przesunąć znaczniki? Rodzaj zaangażowanych firm kłóciłby się o to, kto byłby górny w oknie informacyjnym inaczej (drobna wiem!).
Rob
Dobra robota @Casey. To wygląda świetnie!
RyanKDalton
@Casey Dziękuję za odpowiedź, jak mogę to zrobić w moim kodzie? Mam problem z ponownym przetwarzaniem kodu w ten sposób! Oto moje źródło - view-source: mediwales.com/mapping/members
Rob
@Rob Użyj mojej przykładowej strony jako przewodnika. Jedną dużą różnicą między naszym kodem jest to, że wyciągnąłem kod tworzenia znacznika z kodu adresu geokodu i umieściłem go we własnej funkcji o nazwie createMarker. Trzeba to również zrobić, aby technika szturchania zadziałała.
Casey
@Casey Miałem kilka prób i nie mogę sprawić, żeby zadziałało ... Nie chcę, żeby zabrzmiało to tak, jakbym kazał ci to zrobić, ale próbowałem przez ostatni dzień.
Rob
3

Miałem ten sam problem z kilkoma markerami o dokładnie tej samej długości / długości dla aplikacji z obszarem sprzedaży. To był częsty scenariusz w mojej aplikacji z wieloma klientami pod tym samym adresem, na przykład klientami w tym samym budynku wieżowca, a zatem pod tym samym fizycznym adresem.

Znalazłem alternatywną odpowiedź z być może lepszą obsługą użytkownika (UX) dla nakładających się znaczników. Podziękowania dla George'a MacKerrona za utworzenie biblioteki OverlappingMarkerSpiderfier . Ta biblioteka JavaScript dla Google Maps v3 zastępuje domyślne zachowanie kliknięcia dla nakładających się znaczników. Biblioteka umożliwia skonfigurowanie promienia przesunięcia dla nakładania się (domyślnie 20 pikseli).

Przykładowe zrzuty ekranu z http://jawj.github.io/OverlappingMarkerSpiderfier/demo.html :

Zrzut ekranu nakładających się znaczników przed kliknięciem Zrzut ekranu kliknięcia jednego z nakładających się znaczników Zrzut ekranu kliknięcia znacznika w „spisted” sieci nakładających się znaczników

Steve Jansen
źródło
0

Proponuję zmienić powyższą funkcję w następujący sposób, ponieważ uzyskane wyniki wydają mi się lepsze.

function adjustMarkerPlace(latlng) {
  ///get array of markers currently in cluster 
  //final position for marker, could be updated if another marker already exists in same position
  var finalLatLng = latlng;

  //check to see if any of the existing markers match the latlng of the new marker
  if (markers.length !== 0) {
      for (let i=0; i < markers.length; i++) {
          var existingMarker = markers[i];
          var pos = existingMarker.getPosition();

          //check if a marker already exists in the same position as this marker
          if (latlng.equals(pos)) {

              //update the position of the coincident marker by applying a small multipler to its coordinates
              var newLat = latlng.lat() + (Math.random() / 10000);
              var newLng = latlng.lng() + (Math.random() / 10000);

              finalLatLng = new google.maps.LatLng(newLat,newLng);

          }
      }
  }

  return finalLatLng;

}

Paul Bozan
źródło