138 votes

Google maps API V3 - plusieurs marqueurs exactement au même endroit

Peu coincé sur ce point. Je suis à la recherche d'une liste de geo coords via JSON et sautant sur une carte google. Tout fonctionne bien sauf dans l'instance lorsque j'ai deux marqueurs ou plus exactement au même endroit. L'API n'affiche que 1 marqueur du top. C'est assez juste, je suppose, mais aimerait trouver un moyen de les afficher toutes en quelque sorte.

J'ai cherché sur google et trouvé quelques solutions, mais pour la plupart ils semblent être pour la V2 de l'API ou tout simplement pas grande. Idéalement, j'aimerais une solution où vous cliquez sur une sorte de groupe de marqueur et qui montre les marqueurs regroupés autour de la place, ils sont tous dans.

Quelqu'un a eu ce problème ou similaire et à partager une solution?

123voto

Tad Points 591

Jetez un oeil à OverlappingMarkerSpiderfier.
Il y a une page de démonstration, mais ils ne présentent pas de marqueurs qui sont exactement sur le même spot, seulement quelques-uns qui sont très proches.

Mais un exemple réel avec des marqueurs sur la même place peut être vu sur http://www.ejw.de/ejw-vor-ort/ (faites défiler la carte et cliquez sur un peu de marqueurs de voir l'araignée-effet).

Qui semble être la solution parfaite à votre problème.

39voto

Ignatius Points 201

Compenser les marqueurs n'est pas une vraie solution si ils sont situés dans le même bâtiment. Ce que vous voulez faire est de modifier le markerclusterer.js comme suit:

  1. Ajouter un prototype de la méthode click dans le MarkerClusterer classe, comme nous allons remplacer ce plus tard dans la carte de la fonction initialize ():

    MarkerClusterer.prototype.onClick = function() { 
        return true; 
    };
    
  2. Dans le ClusterIcon catégorie, ajoutez le code suivant APRÈS le clusterclick de déclenchement:

    // 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. Puis, dans votre fonction initialize() lorsque vous initialisez la carte et déclarer votre MarkerClusterer objet:

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

    Où multiChoice() est (pas encore écrits) fonction pour faire apparaître un InfoWindow avec une liste d'options à choisir. Notez que le markerClusterer objet est transmis à votre fonction, car vous en aurez besoin pour déterminer combien de marqueurs il y a dans ce cluster. Par exemple:

    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;
    }
    

15voto

DzinX Points 13452

L'expansion sur Chaoley de réponse, j'ai implémenté une fonction qui, étant donné une liste des endroits objets (avec lng et lat propriétés) dont les coordonnées sont exactement les mêmes, se déplace loin de leur lieu d'origine un peu (modification des objets en place). Il se forme alors un joli cercle autour du point central.

J'ai trouvé que, pour ma latitude (52deg Nord), 0.0003 degrés de cercle de rayon fonctionnent le mieux, et que vous avez à faire la différence entre la latitude et la longitude en degrés lors de la conversion de kilomètres. Vous pouvez trouver approximative de conversions pour votre latitude ici.

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;
    }
};

11voto

Nathan Colgate Points 676

@Ignace plus excellente réponse, mis à jour pour fonctionner avec v2.0.7 de MarkerClustererPlus.

  1. Ajouter un prototype de la méthode click dans le MarkerClusterer classe, comme nous allons remplacer ce plus tard dans la carte de la fonction initialize ():

    // BEGIN MODIFICATION (around line 715)
    MarkerClusterer.prototype.onClick = function() { 
        return true; 
    };
    // END MODIFICATION
    
  2. Dans le ClusterIcon catégorie, ajoutez le code suivant APRÈS le clic/clusterclick de déclenchement:

    // 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. Puis, dans votre fonction initialize() lorsque vous initialisez la carte et déclarer votre MarkerClusterer objet:

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

    Où multiChoice() est (pas encore écrits) fonction pour faire apparaître un InfoWindow avec une liste d'options à choisir. Notez que le markerClusterer objet est transmis à votre fonction, car vous en aurez besoin pour déterminer combien de marqueurs il y a dans ce cluster. Par exemple:

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

3voto

Chaoley Points 415

Dans les cas où il existe plusieurs services dans le même bâtiment, vous pouvez légèrement décaler les repères (disons de 0,001 degré) dans un rayon égal au point réel. Cela devrait également produire un bel effet visuel.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X