29

Mi piace creare una mappa con Google Maps in grado di gestire grandi quantità di indicatori (oltre 10.000). Per non rallentare la mappa, ho creato un file XML che emette solo i marker all'interno della finestra corrente.Google Maps V3: mostra solo marcatori nella vista - Cancella problema marcatori

In primo luogo, io uso inizializzazione() per impostare le opzioni della mappa:

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

Quando l'evento 'tilesloaded' è finito, io uso loadMapFromCurrentBounds(), questa funzione sarà possibile ottenere i limiti attuali e invia una richiesta al-file XML per mostrare i marcatori che si trovano all'interno della finestra corrente:

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

Questo sta lavorando molto, tuttavia, il codice corrente non offload marcatori che non sono in de viewport più. Oltre a ciò, carica nuovamente i marker già caricati, che rallenta la mappa molto velocemente quando si spostano la mappa con tempi di visualizzazione nella stessa area.

Quindi, quando la finestra di visualizzazione cambia, mi piace cancellare l'intera mappa prima di caricare nuovi indicatori. Qual è il modo migliore per farlo?

+0

Hey @jeff, thx per le modifiche! Volevo solo farti sapere che puoi effettivamente aggiungere l'evidenziazione della sintassi a * tutte * le risposte su una domanda semplicemente aggiungendo il tag 'JavaScript', usando il link" modifica tag "che appare a destra dei tag. In bocca al lupo! :) – jmort253

+0

Il [Marker Clusterer] (https://code.google.com/p/google-maps-utility-library-v3/wiki/Libraries) potrebbe essere utile quando si ha a che fare con così tanti marcatori. – Blazemonger

+1

puoi salvare poche righe di codice facendo 'map.getBounds(). AUrlValue(). Split (',')' e avrai una bella matrice per i tuoi angoli. – tim

risposta

15

è necessario aggiungere un altro ascoltatore di eventi alla mappa:

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

Vedi here per più sulla rimozione di tutti gli indicatori da una mappa di google - purtroppo non penso che può essere fatto con una sola chiamata. Così si dovrà scrivere le removeMarkers o qualcosa di simile, che dovranno scorrere tutti gli indicatori sulla mappa rimuoverli singolarmente in questo modo:

markersArray[i].setMap(null); 

Non so se è più rapido per verificare se il marcatore è nella finestra prima di rimuovere utilizzando:

map.getBounds(); 

Read more about Google Map API v3 events

+0

Grazie per la tua risposta! Perché devo usare "bounds_changed"? Il listener di eventi che sto usando ora ('Tilesloaded') sembra fare lo stesso, ogni volta che la finestra cambia le funzioni loadMapFromCurrentBounds() viene chiamato. Ho provato markersArray [i] .setMap (null); ma non funziona. Oltre a questo, mi piacciono le soluzioni in cui ho solo cancellato i marcatori che non sono più nella finestra di visualizzazione ... Proverò a caricare un esempio più tardi questa sera! – Thijs

+2

inoltre, i tilesload non possono sparare se stai spostando la mappa solo un po ', cioè se il tuo movimento non causa il caricamento di una nuova tessera nella vista – tim

6

Si consiglia di controllare questo thread. Daniel ha risposto abbastanza bene.

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

Inoltre, bounds_changed è la prima occasione per richiamare la funzione. caricato, sarà chiamato costantemente. Il viewport può contenere più di una tessera per riempire il viewport.

In alternativa, è possibile anche impostare un setVisible (false).

Per rimuovere il marker, potrebbe essere necessario rimuovere gli ascoltatori.

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

Questo articolo va attraverso di essa abbastanza bene: Dynamically loading thousands of markers in Google Maps

  • caricare dinamicamente marcatori fino a raggiungere una soglia
  • mantenere una tabella hash di marcatori che sono stati già aggiunti
  • dopo la soglia è stata raggiunta, rimuovere i marcatori che non si trovano attualmente nella vista
  • rimuovere tutti i marcatori dalla mappa quando l'utente ha zoom indietro, e non caricare i marcatori fino a quando l'utente ingrandisce di nuovo ad un livello ragionevole
+1

Link non funziona più. –

+3

Prova questo link http://xyzzyb.tumblr.com/post/10317033064/dynamically-loading-thousands-of-markers-in-google-maps – webjunkie

1

La vostra funzione originale sembra come un sacco di codice. Mi piacerebbe fare qualcosa di simile:

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

Si potrebbe voler controllare questa documentazione da Google. Spiega quello che vi serve:

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)). 
Problemi correlati