Marcadores do Google no mesmo endereço que não mostram todos os marcadores

16

Eu tenho trabalhado neste mapa - http://www.mediwales.com/mapping/test/

Ele está planejando bem as empresas e agrupando-as ok, mas surgiu um problema com as empresas no mesmo prédio, com o mesmo endereço. Está mostrando apenas uma empresa em vez de todas elas.

Como posso exibir todas as empresas no mesmo endereço?

Os marcadores são geocodificados pelo nome / número da construção, rua, cidade, código postal. Eu estou supondo que os marcadores estão lá como um edifício que tem 3 empresas mostra um 3 no cluster. No entanto, quando você clica no botão, ele mostra apenas a única empresa.

ATUALIZAR:

Eu consegui fazê-los compensar, mas está compensando todos os marcadores quando eu só quero compensar se houver mais de um marcador igual. (Graças à resposta 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>
Roubar
fonte

Respostas:

15

O clusterer está sendo exibido corretamente. Todos os marcadores estão sendo plotados. O problema é que você só pode clicar no marcador superior, fazendo parecer que existe apenas um marcador.

Para ver o conteúdo dos marcadores coincidentes, você precisará passar o conteúdo da janela de entrada dos marcadores subjacentes para o marcador mais alto.

Para fazer isso, primeiro, mantenha o controle de cada marcador. Você está usando MarkerClusterer, portanto, a instância markerClusterer manterá cada marcador. À medida que cada resultado de geocódigo volta, compare a latência dessa solicitação com todos os marcadores que já foram plotados. Você pode comparar posições usando o método equals da latlng objeto .

Se o novo marcador corresponder à posição de um marcador existente, pegue o conteúdo da janela de entrada do primeiro marcador e anexe-o ao conteúdo da janela de entrada do novo marcador. Dessa forma, quando você clica no marcador superior (a segunda empresa), ele mostra informações das duas empresas. Se houver mais de duas empresas, você precisará capturar o conteúdo da janela de entrada de todos os marcadores correspondentes. Esse método também permitirá que o clusterer de marcadores ainda exiba o número correto de marcadores.

Aqui está um exemplo de trabalho e o código javascript. O primeiro e o segundo endereços são os mesmos. Quando você clica no marcador para 2, ele mostra "2 e 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> 

EDIT: Resposta ao comentário

Como alternativa, você pode deslocar marcadores coincidentes aplicando um pequeno (número aleatório entre .999999 e 1.000001, por exemplo) multiplicador na posição de cada marcador coincidente. Aqui está um exemplo. Isso está usando os mesmos dados do primeiro exemplo, exceto que, em vez de os marcadores 1 e 2 serem colocados um em cima do outro e compartilharem uma janela de informações, o marcador 2 é deslocado do marcador 1. Observe que os resultados do seu geocódigo serão um um pouco menos preciso. Código relevante abaixo:

//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
fonte
Obrigado pela resposta. Voltando a este projeto! Certo, seria possível compensar um pouco os marcadores? O tipo de empresa envolvida argumentaria quem era o melhor na janela de informações (caso contrário, eu sei!).
Rob
Bom trabalho, @Casey. Isso parece ótimo!
RyanKDalton-OffTheGridMaps
@ Casey Obrigado pela resposta, como eu poderia trabalhar isso no meu código? Eu luto com o retrabalho de código como este! Aqui está a minha fonte - view-source: mediwales.com/mapping/members
Rob
@Rob Use minha página de exemplo como guia. Uma grande diferença entre nosso código é que eu retirei meu código de marcador de criação do meu código de endereço de geocódigo e o coloquei em sua própria função chamada createMarker. Você precisará fazer isso também para que a técnica de nudge funcione.
Casey
@ Casey Eu tive algumas tentativas e não consigo fazê-lo funcionar ... Eu não quero que pareça que estou conseguindo que você faça isso, mas tenho tentado durante o último dia.
Rob
3

Eu tive o mesmo problema com vários marcadores exatamente no mesmo lat / long para um aplicativo de território de vendas. Esse era um cenário comum no meu aplicativo com vários clientes no mesmo endereço, por exemplo, clientes no mesmo prédio de arranha-céu e, portanto, no mesmo endereço físico.

Encontrei uma resposta alternativa com talvez uma melhor experiência do usuário (UX) para marcadores sobrepostos. Agradecimentos a George MacKerron por criar a biblioteca OverlappingMarkerSpiderfier . Esta biblioteca JavaScript do Google Maps v3 substitui o comportamento padrão de cliques de marcadores sobrepostos. A biblioteca permite configurar o raio de deslocamento para sobreposição (o padrão é 20 pixels).

Exemplo de capturas de tela de http://jawj.github.io/OverlappingMarkerSpiderfier/demo.html :

Captura de tela dos marcadores sobrepostos antes de clicar Captura de tela de clicar em qualquer um dos marcadores sobrepostos Captura de tela de clicar em um marcador na teia "aranha" de marcadores sobrepostos

Steve Jansen
fonte
0

Proponho alterar a função acima da seguinte maneira, porque os resultados obtidos me parecem melhores.

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
fonte