29

J'aime créer une carte avec Google Maps qui peut gérer de grandes quantités de marqueurs (plus de 10.000). Pour ne pas ralentir la carte, j'ai créé un fichier XML qui affiche uniquement les marqueurs qui se trouvent dans la fenêtre courante.Google Maps V3: Afficher uniquement les marqueurs dans viewport - Effacer les marqueurs

D'abord, j'utilise initialiser() pour configurer les options de carte:

function initialize() { 
    var myLatlng = new google.maps.LatLng(51.25503952021694,3.27392578125); 
    var myOptions = { 
     zoom: 8, 
     center: myLatlng, 
     mapTypeId: google.maps.MapTypeId.ROADMAP 
    } 
    var map = new google.maps.Map(document.getElementById("map_canvas"), myOptions); 

    google.maps.event.addListener(map, 'tilesloaded', function() { 
    loadMapFromCurrentBounds(map); 
    }); 
} 

Lorsque l'événement « tilesloaded » est terminé, j'utilise loadMapFromCurrentBounds(), cette fonctions sera les limites actuelles et envoie une demande le fichier XML pour montrer les marqueurs qui sont dans la fenêtre courante:

function loadMapFromCurrentBounds(map) { 

    // First, determine the map bounds 
    var bounds = map.getBounds(); 

    // Then the points 
    var swPoint = bounds.getSouthWest(); 
    var nePoint = bounds.getNorthEast(); 

    // Now, each individual coordinate 
    var swLat = swPoint.lat(); 
    var swLng = swPoint.lng(); 
    var neLat = nePoint.lat(); 
    var neLng = nePoint.lng(); 

    downloadUrl("mapsxml.php?swLat="+swLat+"&swLng="+swLng+"&neLat="+neLat+"&neLng="+neLng+"", function(data) { 
     var xml = parseXml(data); 
     var markers = xml.documentElement.getElementsByTagName("marker"); 
     var infoWindow = new google.maps.InfoWindow; 

     for (var i = 0; i < markers.length; i++) { 
      var address = markers[i].getAttribute("address"); 
      var type = markers[i].getAttribute("type"); 
      var name = markers[i].getAttribute("name"); 

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

      bindInfoWindow(marker, map, infoWindow, html); 
     } 
    }) 
} 

Cela fonctionne très bien, cependant, le code actuel n'Offload pas les marqueurs qui ne sont pas de plus viewport. En plus de cela, il charge à nouveau des marqueurs qui sont déjà chargés, ce qui ralentit la carte très rapidement en déplaçant la carte une fois dans la même zone.

Ainsi, lorsque la fenêtre d'affichage change, j'aime effacer toute la carte avant de charger de nouveaux marqueurs. Quelle est la meilleure façon de procéder?

+0

Hey @ Jeff, thx pour les modifications! Je voulais juste que vous sachiez que vous pouvez ajouter de la syntaxe en surlignant * toutes * les réponses à une question en ajoutant simplement la balise «JavaScript», en utilisant le lien «modifier les balises» qui apparaît à droite des balises. Bonne chance! :) – jmort253

+0

Le [Marker Clusterer] (https://code.google.com/p/google-maps-utility-library-v3/wiki/Libraries) peut s'avérer utile pour gérer autant de marqueurs. – Blazemonger

+1

vous pouvez enregistrer quelques lignes de code ci-dessus en faisant 'map.getBounds(). ToUrlValue(). Split (',')' et avoir un bon tableau pour vos coins. – tim

Répondre

15

Vous devez ajouter un autre événement Listener à la carte:

google.maps.event.addListener(map,'bounds_changed', removeMarkers); 

Voir here pour plus sur la suppression de tous les marqueurs d'une carte google - malheureusement, je ne pense pas qu'il peut être fait avec un seul appel. Donc, vous devrez écrire les removeMarkers ou quelque chose de similaire qui devront parcourir tous les marqueurs sur la carte les supprimer individuellement comme ceci:

markersArray[i].setMap(null); 

Je ne sais pas s'il est plus rapide de vérifier si le marqueur est dans la fenêtre avant de retirer à l'aide:

map.getBounds(); 

Read more about Google Map API v3 events

+0

Merci pour votre réponse! Pourquoi dois-je utiliser 'bounds_changed'? L'écouteur d'événement que j'utilise maintenant ('Tilesloaded') semble faire la même chose, chaque fois que la fenêtre d'affichage change les fonctions loadMapFromCurrentBounds() est appelée. J'ai essayé markersArray [i] .setMap (null); mais ça ne marche pas. A part ça, j'aime les solutions où je supprime seulement les marqueurs qui ne sont plus dans la fenêtre d'affichage ... Je vais essayer de télécharger un exemple plus tard dans la soirée! – Thijs

+2

également, tilesloaded ne peut pas tirer si vous déplacez la carte juste un peu, c'est-à-dire si votre mouvement n'entraîne pas le chargement d'une nouvelle vignette dans la fenêtre – tim

6

Vous pouvez consulter ce fil. Daniel a répondu cela très bien.

What's the most efficient way to create routes on google maps from gps files?

En outre, bounds_changed est la première occasion d'appeler votre fonction. tilesloaded, sera appelé en permanence. La fenêtre peut contenir plusieurs mosaïques pour remplir la fenêtre.

Vous pouvez également faire un setVisible (false). Pour supprimer le marqueur, vous devrez peut-être supprimer les écouteurs.

google.maps.event.clearInstanceListeners(marker); 
marker.setMap(null); 
markers.remove(marker); 
delete marker; 
4

Cet article va à travers elle assez bien: Dynamically loading thousands of markers in Google Maps

  • charger dynamiquement des marqueurs jusqu'à atteindre un seuil
  • garder un Hashtable de marqueurs qui ont déjà été ajoutés
  • après le seuil a été atteint, supprimez les marqueurs qui ne sont pas actuellement dans la fenêtre
  • supprimer tous les marqueurs de la carte lorsque l'utilisateur a zoomé sur, et ne pas charger les marqueurs jusqu'à ce que l'utilisateur effectue un zoom à un niveau raisonnable
+1

Le lien ne fonctionne plus. –

+3

Essayez ce lien http://xyzzyb.tumblr.com/post/10317033064/dynamically-loading-thousands-of-markers-in-google-maps – webjunkie

1

Votre fonction d'origine semble comme beaucoup de code. Je ferais quelque chose comme ceci:

if(map.getBounds().contains(markers[i].getPosition())) { 
    myMarkerDisplayFunction(markers[i]); 
} 
0

Vous pouvez consulter cette documentation de Google. Il explique ce que vous avez besoin:

With the new list of markers you can remove the current markers 
(marker.setMap(null)) that are on the map and 
add the new ones (marker.setMap(map)). 
5

En raison de l'explication suivante à l'aide « tilesloaded » ou « bounds_changed » serait très mal et provoquer des mises à feu continu ne veulent pas. Au lieu de cela, vous voudriez utiliser l'événement "inactif" qui se déclenchera une fois que l'utilisateur aura arrêté le panoramique/zoom.

google.maps.event.addListener (carte, 'idle', loadMapFromCurrentBounds);

https://developers.google.com/maps/articles/toomanymarkers#viewportmarkermanagement