Los marcadores de Google en la misma dirección no muestran todos los marcadores

16

He estado trabajando en este mapa: http://www.mediwales.com/mapping/test/

Está trazando bien a las compañías y agrupándolas bien, pero ha surgido un problema con las compañías en el mismo edificio con la misma dirección. Solo muestra una compañía en lugar de todas.

¿Cómo puedo hacer que muestre todas las empresas en la misma dirección?

Los marcadores están geocodificados por nombre / número de edificio, calle, ciudad, código postal. Supongo que los marcadores están ahí, ya que un edificio que tiene 3 compañías muestra un 3 en el clúster. Sin embargo, cuando hace clic en él, solo muestra la única empresa.

ACTUALIZAR:

Me las he arreglado para compensarlos, pero está compensando todos los marcadores cuando solo quiero que se compensen si hay más de un marcador igual. (Gracias a la respuesta de 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>
Robar
fuente

Respuestas:

15

El clusterer se muestra correctamente. Todos los marcadores están siendo trazados. El problema es que solo puede hacer clic en el marcador superior, lo que hace que parezca que solo hay un marcador.

Para ver el contenido de los marcadores coincidentes, deberá pasar el contenido de la ventana de información de los marcadores subyacentes al marcador superior.

Para hacer esto, primero, realice un seguimiento de cada marcador. Está utilizando MarkerClusterer, por lo que la instancia de markerClusterer contendrá cada marcador. A medida que regresa el resultado de cada geocodificación, compare el latlng de esa solicitud con todos los marcadores que ya se han trazado. Puede comparar posiciones utilizando el método igual del objeto latlng .

Si el nuevo marcador coincide con la posición de un marcador existente, tome el contenido de la ventana de información del primer marcador y agréguelo al contenido de la ventana de información del nuevo marcador. De esta manera, cuando hace clic en el marcador superior (la segunda compañía), mostrará información de ambas compañías. Si hay más de dos compañías, deberá tomar el contenido de la ventana de información para todos los marcadores coincidentes. Este método también permitirá que el grupo de marcadores muestre el número correcto de marcadores.

Aquí hay un ejemplo de trabajo y el código javascript. La primera y la segunda dirección son iguales. Cuando hace clic en el marcador de 2, mostrará "2 y 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> 

EDITAR: respuesta al comentario

Alternativamente, puede empujar marcadores coincidentes aplicando un pequeño (número aleatorio entre .999999 y 1.000001, por ejemplo) multiplicador a la posición de cada marcador coincidente. Aquí hay un ejemplo. Esto está utilizando los mismos datos que el primer ejemplo, excepto que, en lugar de que los marcadores 1 y 2 se coloquen uno encima del otro y compartan una ventana de información, el marcador 2 está desplazado del marcador 1. Tenga en cuenta que los resultados de su geocodificación serán Poco menos preciso. Código relevante a continuación:

//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
fuente
Gracias por la respuesta. ¡Acabo de volver a este proyecto! Bien, ¿sería posible compensar un poco los marcadores? De lo contrario, el tipo de empresas involucradas argumentaría quién era el primero en la ventana de información (¡insignificante, lo sé!).
Rob
Buen trabajo @Casey. ¡Eso se ve genial!
RyanKDalton-OffTheGridMaps
@Casey Gracias por la respuesta, ¿cómo podría incluir eso en mi código? ¡Lucho con la reelaboración de código como este! Aquí está mi fuente - ver-fuente: mediwales.com/mapping/members
Rob
@Rob Usar mi página de ejemplo como guía. Una gran diferencia entre nuestro código es que saqué mi código de marcador de creación de mi código de dirección de geocodificación y lo puse en su propia función llamada createMarker. Tendrá que hacer esto también para que la técnica de empuje funcione.
Casey
@Casey He tenido un par de intentos y no puedo hacer que funcione ... No quiero que suene como si solo estuviera haciendo que lo hagas, pero lo he estado intentando el último día.
Rob
3

Tuve el mismo problema con varios marcadores exactamente en el mismo lat / long para una aplicación de territorio de ventas. Este era un escenario común en mi aplicación con múltiples clientes en la misma dirección, por ejemplo, clientes en el mismo edificio de rascacielos y, por lo tanto, en la misma dirección física.

Encontré una respuesta alternativa con quizás una mejor experiencia de usuario (UX) para los marcadores superpuestos. Gracias a George MacKerron por crear la biblioteca OverlappingMarkerSpiderfier . Esta biblioteca de JavaScript para Google Maps v3 anula el comportamiento de clic predeterminado para los marcadores superpuestos. La biblioteca le permite configurar el radio de desplazamiento para la superposición (el valor predeterminado es 20 píxeles).

Capturas de pantalla de ejemplo de http://jawj.github.io/OverlappingMarkerSpiderfier/demo.html :

Captura de pantalla de marcadores superpuestos antes de hacer clic Captura de pantalla de hacer clic en cualquiera de los marcadores superpuestos Captura de pantalla de hacer clic en un marcador en la red "arañada" de marcadores superpuestos

Steve Jansen
fuente
0

Propongo cambiar la función anterior de la siguiente manera porque los resultados obtenidos me parecen mejores.

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
fuente