Marqueurs Google à la même adresse ne montrant pas tous les marqueurs

16

J'ai travaillé sur cette carte - http://www.mediwales.com/mapping/test/

Cela permet de bien tracer les entreprises et de les regrouper correctement, mais un problème est survenu avec les entreprises du même bâtiment avec la même adresse. Cela ne montre qu'une seule entreprise plutôt que toutes.

Comment puis-je faire afficher toutes les entreprises à la même adresse?

Les marqueurs sont géocodés par nom / numéro de bâtiment, rue, ville, code postal. Je suppose que les marqueurs sont là, car un bâtiment qui compte 3 entreprises affiche 3 dans le cluster. Pourtant, lorsque vous cliquez dessus, il ne montre qu'une seule entreprise.

MISE À JOUR:

J'ai réussi à les faire compenser, mais cela compense tous les marqueurs quand je veux seulement qu'ils compensent s'il y a plusieurs marqueurs identiques. (Merci à la réponse 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>
Rob
la source

Réponses:

15

Le clusterer s'affiche correctement. Tous les marqueurs sont tracés. Le problème est que vous ne pouvez cliquer que sur le marqueur le plus haut, ce qui donne l'impression qu'il n'y a qu'un seul marqueur.

Pour voir le contenu des marqueurs coïncidents, vous devez passer le contenu de la sous-fenêtre des marqueurs sous-jacents au marqueur le plus haut.

Pour ce faire, tout d'abord, gardez une trace de chaque marqueur. Vous utilisez MarkerClusterer, donc l'instance markerClusterer contiendra chaque marqueur. Lorsque chaque résultat de géocodage revient, comparez le retard de cette demande avec tous les marqueurs qui ont déjà été tracés. Vous pouvez comparer des positions en utilisant la méthode equals de l' objet latlng .

Si le nouveau marqueur correspond à la position d'un marqueur existant, prenez le contenu de la sous-fenêtre du premier marqueur et ajoutez-le au contenu de la nouvelle fenêtre du marqueur. De cette façon, lorsque vous cliquez sur le marqueur le plus haut (la deuxième entreprise), il affichera les informations des deux entreprises. S'il y a plus de deux sociétés, vous devrez récupérer le contenu de la sous-fenêtre pour tous les marqueurs correspondants. Cette méthode permettra également à l'agrégateur de marqueurs d'afficher toujours le nombre correct de marqueurs.

Voici un exemple de travail et le code javascript. Les première et deuxième adresses sont identiques. Lorsque vous cliquez sur le marqueur pour 2, il affichera "2 & 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: Réponse au commentaire

Alternativement, vous pouvez pousser les marqueurs coïncidents en appliquant un petit multiplicateur (nombre aléatoire entre .999999 et 1.000001, par exemple) à la position de chaque marqueur coïncident. Voici un exemple. Cela utilise les mêmes données que le premier exemple, sauf que, au lieu que les marqueurs 1 et 2 soient placés les uns sur les autres et partagent une sous-fenêtre, le marqueur 2 est décalé du marqueur 1. Notez que vos résultats de géocodage vont être un peu moins précis. Code pertinent ci-dessous:

//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
la source
Merci pour la réponse. Revenons à ce projet! D'accord, serait-il possible de décaler un peu les marqueurs? Dans le cas contraire, le type d'entreprises impliquées se demanderait qui était le meilleur dans la fenêtre d'informations (mesquin je sais!).
Rob
Beau travail @Casey. Ça a l'air génial!
RyanKDalton-OffTheGridMaps
@Casey Merci pour la réponse, comment pourrais-je intégrer cela dans mon code? J'ai du mal à retravailler du code comme celui-ci! Voici ma source - view-source: mediwales.com/mapping/members
Rob
@Rob Utilisez ma page d'exemple comme guide. Une grande différence entre notre code est que j'ai retiré mon code de marqueur de création de mon code d'adresse de géocodage et l'ai mis dans sa propre fonction appelée createMarker. Vous devrez également le faire pour que la technique du coup de pouce fonctionne.
Casey
@Casey J'ai eu quelques tentatives et je n'arrive pas à le faire fonctionner ... Je ne veux pas que ça sonne comme si je vous demandais de le faire, mais j'essaie depuis le dernier jour.
Rob
3

J'ai eu le même problème avec plusieurs marqueurs exactement au même lat / long pour une application de territoire de vente. C'était un scénario courant dans mon application avec plusieurs clients à la même adresse, par exemple des clients dans le même immeuble de gratte-ciel et donc à la même adresse physique.

J'ai trouvé une réponse alternative avec peut-être une meilleure expérience utilisateur (UX) pour les marqueurs qui se chevauchent. Merci à George MacKerron d'avoir créé la bibliothèque OverlappingMarkerSpiderfier . Cette bibliothèque JavaScript pour Google Maps v3 remplace le comportement de clic par défaut pour les marqueurs qui se chevauchent. La bibliothèque vous permet de configurer le rayon de décalage pour le chevauchement (par défaut à 20 pixels).

Exemples de captures d'écran de http://jawj.github.io/OverlappingMarkerSpiderfier/demo.html :

Capture d'écran des marqueurs qui se chevauchent avant de cliquer Capture d'écran d'un clic sur l'un des marqueurs qui se chevauchent Capture d'écran d'un clic sur un marqueur dans la toile "araignée" de marqueurs qui se chevauchent

Steve Jansen
la source
0

Je propose de modifier la fonction ci-dessus comme suit car les résultats obtenus me semblent meilleurs.

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
la source