API di JS per Google Maps v3 – Esempio di più marker multipli

Abbastanza nuovo per l’API di Google Maps. Ho una serie di dati che voglio scorrere e tracciare su una mappa. Sembra abbastanza semplice, ma tutti i tutorial multi-marker che ho trovato sono piuttosto complessi.

Usiamo l’array di dati dal sito di Google per un esempio:

var locations = [ ['Bondi Beach', -33.890542, 151.274856, 4], ['Coogee Beach', -33.923036, 151.259052, 5], ['Cronulla Beach', -34.028249, 151.157507, 3], ['Manly Beach', -33.80010128657071, 151.28747820854187, 2], ['Maroubra Beach', -33.950198, 151.259302, 1] ]; 

Voglio semplicemente tracciare tutti questi punti e far apparire una finestra di informazioni quando si fa clic per visualizzare il nome.

Questo è il modo più semplice per ridurlo a:

 < !DOCTYPE html>    Google Maps Multiple Markers    

Immagine dello schermo:

Google Maps più marcatori

C'è una certa magia di chiusura che si verifica quando si passa l'argomento di callback al metodo addListener . Questo può essere un argomento piuttosto complicato, se non si ha familiarità con il modo in cui funzionano le chiusure. Suggerirei di controllare il seguente articolo di Mozilla per una breve introduzione, se è il caso:

  • Mozilla Dev Center: Working with Closures

Ecco un altro esempio di caricamento di più marker con un title univoco e infoWindow testo di infoWindow . Testato con l’ultima API di google maps V3.11.

 < !DOCTYPE html>     Multiple Markers Google Maps      

Schermata di 250 marcatori:

API di Google Maps V3.11 con più indicatori

Rende automaticamente casuale il Lat / Lng per renderlo unico. Questo esempio sarà molto utile se si desidera testare 500, 1000, marcatori xxx e prestazioni.

Ho pensato di inserirlo qui in quanto sembra essere un punto di atterraggio popolare per chi inizia a utilizzare le API di Google Maps. Marcatori multipli resi sul lato client sono probabilmente la rovina di molte prestazioni delle applicazioni di mapping. È difficile fare benchmark, correggere e in alcuni casi anche stabilire un problema (a causa delle differenze di implementazione del browser, dell’hardware disponibile per il client, dei dispositivi mobili, l’elenco continua).

Il modo più semplice per iniziare a risolvere questo problema è utilizzare una soluzione di clustering dei marker. L’idea di base è raggruppare località geograficamente simili in un gruppo con il numero di punti visualizzati. Quando l’utente ingrandisce la mappa, questi gruppi si espandono per rivelare i singoli marcatori sottostanti.

Forse la più semplice da implementare è la libreria markerclusterer . Un’implementazione di base sarebbe la seguente (dopo le importazioni della biblioteca):

  

I marcatori invece di essere aggiunti direttamente alla mappa vengono aggiunti a un array. Questo array viene quindi passato alla libreria che gestisce il calcolo complesso per te e collegato alla mappa.

Queste implementazioni non solo aumentano enormemente le prestazioni lato client, ma in molti casi portano a un'interfaccia utente più semplice e meno ingombrante ea una più facile digestione dei dati su scale più grandi.

Altre implementazioni sono disponibili da Google.

Spero che questo aiuti alcuni di quelli più recenti per le sfumature della mapping.

Versione asincrona:

  

Questa è l'immagine della mappa di esempio di lavoro

 var arr = new Array(); function initialize() { var i; var Locations = [ { lat:48.856614, lon:2.3522219000000177, address:'Paris', gval:'25.5', aType:'Non-Commodity', title:'Paris', descr:'Paris' }, { lat: 55.7512419, lon: 37.6184217, address:'Moscow', gval:'11.5', aType:'Non-Commodity', title:'Moscow', descr:'Moscow Airport' }, { lat:-9.481553000000002, lon:147.190242, address:'Port Moresby', gval:'1', aType:'Oil', title:'Papua New Guinea', descr:'Papua New Guinea 123123123' }, { lat:20.5200, lon:77.7500, address:'Indore', gval:'1', aType:'Oil', title:'Indore, India', descr:'Airport India' } ]; var myOptions = { zoom: 2, center: new google.maps.LatLng(51.9000,8.4731), mapTypeId: google.maps.MapTypeId.ROADMAP }; var map = new google.maps.Map(document.getElementById("map"), myOptions); var infowindow = new google.maps.InfoWindow({ content: '' }); for (i = 0; i < Locations.length; i++) { size=15; var img=new google.maps.MarkerImage('marker.png', new google.maps.Size(size, size), new google.maps.Point(0,0), new google.maps.Point(size/2, size/2) ); var marker = new google.maps.Marker({ map: map, title: Locations[i].title, position: new google.maps.LatLng(Locations[i].lat, Locations[i].lon), icon: img }); bindInfoWindow(marker, map, infowindow, "

" + Locations[i].descr + "",Locations[i].title); } } function bindInfoWindow(marker, map, infowindow, html, Ltitle) { google.maps.event.addListener(marker, 'mouseover', function() { infowindow.setContent(html); infowindow.open(map, marker); }); google.maps.event.addListener(marker, 'mouseout', function() { infowindow.close(); }); }

Pieno esempio di lavoro. Puoi semplicemente copiare, incollare e usare.

Dai campioni dell’API di Google Maps :

 function initialize() { var myOptions = { zoom: 10, center: new google.maps.LatLng(-33.9, 151.2), mapTypeId: google.maps.MapTypeId.ROADMAP } var map = new google.maps.Map(document.getElementById("map_canvas"), myOptions); setMarkers(map, beaches); } /** * Data for the markers consisting of a name, a LatLng and a zIndex for * the order in which these markers should display on top of each * other. */ var beaches = [ ['Bondi Beach', -33.890542, 151.274856, 4], ['Coogee Beach', -33.923036, 151.259052, 5], ['Cronulla Beach', -34.028249, 151.157507, 3], ['Manly Beach', -33.80010128657071, 151.28747820854187, 2], ['Maroubra Beach', -33.950198, 151.259302, 1] ]; function setMarkers(map, locations) { // Add markers to the map // Marker sizes are expressed as a Size of X,Y // where the origin of the image (0,0) is located // in the top left of the image. // Origins, anchor positions and coordinates of the marker // increase in the X direction to the right and in // the Y direction down. var image = new google.maps.MarkerImage('images/beachflag.png', // This marker is 20 pixels wide by 32 pixels tall. new google.maps.Size(20, 32), // The origin for this image is 0,0. new google.maps.Point(0,0), // The anchor for this image is the base of the flagpole at 0,32. new google.maps.Point(0, 32)); var shadow = new google.maps.MarkerImage('images/beachflag_shadow.png', // The shadow image is larger in the horizontal dimension // while the position and offset are the same as for the main image. new google.maps.Size(37, 32), new google.maps.Point(0,0), new google.maps.Point(0, 32)); // Shapes define the clickable region of the icon. // The type defines an HTML <area> element 'poly' which // traces out a polygon as a series of X,Y points. The final // coordinate closes the poly by connecting to the first // coordinate. var shape = { coord: [1, 1, 1, 20, 18, 20, 18 , 1], type: 'poly' }; for (var i = 0; i < locations.length; i++) { var beach = locations[i]; var myLatLng = new google.maps.LatLng(beach[1], beach[2]); var marker = new google.maps.Marker({ position: myLatLng, map: map, shadow: shadow, icon: image, shape: shape, title: beach[0], zIndex: beach[3] }); } } 

Ecco un’altra versione che ho scritto per salvare la proprietà della mappa, che colloca il puntatore infowindow sull’attuale lat e long del marker, nascondendo temporaneamente il marker mentre viene visualizzata la finestra di infowindow.

Inoltre, elimina l’assegnazione standard del “marker” e accelera l’elaborazione assegnando direttamente il nuovo marker alla matrice dei marker sulla creazione dei marker. Nota comunque che sono state aggiunte proprietà aggiuntive sia al marker che al infowindow, quindi questo approccio è un po ‘non convenzionale … ma sono io!

Non viene mai menzionato in queste domande a prima vista, che l’infowindow standard NON è posizionato al lat and lng del punto marker, ma piuttosto nella parte superiore dell’immagine del marker. La visibilità dell’indicatore deve essere nascosta perché funzioni, altrimenti l’API di Maps rimetterà di nuovo l’ancoraggio di infowindow nella parte superiore dell’immagine del marcatore.

Il riferimento ai marcatori nella matrice ‘marcatori’ viene creato immediatamente dopo la dichiarazione del marcatore per eventuali attività di elaborazione aggiuntive che possono essere richieste in seguito (hide / mostrare, afferrare le corde, ecc …). Ciò consente di risparmiare il passo aggiuntivo di assegnare l’object marker a “marker” e quindi di premere il “marker” sull’array dei marker … un sacco di elaborazione non necessaria nel mio libro.

Ad ogni modo, un approccio diverso a infowindows, e spero che ti aiuti a informarti e ispirarti.

  var locations = [ ['Bondi Beach', -33.890542, 151.274856, 4], ['Coogee Beach', -33.923036, 151.259052, 5], ['Cronulla Beach', -34.028249, 151.157507, 3], ['Manly Beach', -33.80010128657071, 151.28747820854187, 2], ['Maroubra Beach', -33.950198, 151.259302, 1] ]; var map; var markers = []; function init(){ map = new google.maps.Map(document.getElementById('map_canvas'), { zoom: 10, center: new google.maps.LatLng(-33.92, 151.25), mapTypeId: google.maps.MapTypeId.ROADMAP }); var num_markers = locations.length; for (var i = 0; i < num_markers; i++) { markers[i] = new google.maps.Marker({ position: {lat:locations[i][1], lng:locations[i][2]}, map: map, html: locations[i][0], id: i, }); google.maps.event.addListener(markers[i], 'click', function(){ var infowindow = new google.maps.InfoWindow({ id: this.id, content:this.html, position:this.getPosition() }); google.maps.event.addListenerOnce(infowindow, 'closeclick', function(){ markers[this.id].setVisible(true); }); this.setVisible(false); infowindow.open(map); }); } } google.maps.event.addDomListener(window, 'load', init); 

Ecco un JSFiddle funzionante

Nota aggiuntiva
Noterai in questi dati di esempio di Google un quarto posto nell'array "locations" con un numero. Dato questo nell'esempio, è ansible utilizzare questo valore anche per l'identificatore al posto del valore corrente del loop, in modo che ...

 var num_markers = locations.length; for (var i = 0; i < num_markers; i++) { markers[i] = new google.maps.Marker({ position: {lat:locations[i][1], lng:locations[i][2]}, map: map, html: locations[i][0], id: locations[i][3], }); }; 

Risposta accettata, riscritta in ES6:

 $(document).ready(() => { const mapEl = $('#our_map').get(0); // OR document.getElementById('our_map'); // Display a map on the page const map = new google.maps.Map(mapEl, { mapTypeId: 'roadmap' }); const buildings = [ { title: 'London Eye, London', coordinates: [51.503454, -0.119562], info: 'carousel' }, { title: 'Palace of Westminster, London', coordinates: [51.499633, -0.124755], info: 'palace' } ]; placeBuildingsOnMap(buildings, map); }); const placeBuildingsOnMap = (buildings, map) => { // Loop through our array of buildings & place each one on the map const bounds = new google.maps.LatLngBounds(); buildings.forEach((building) => { const position = { lat: building.coordinates[0], lng: building.coordinates[1] } // Stretch our bounds to the newly found marker position bounds.extend(position); const marker = new google.maps.Marker({ position: position, map: map, title: building.title }); const infoWindow = new google.maps.InfoWindow(); // Allow each marker to have an info window google.maps.event.addListener(marker, 'click', () => { infoWindow.setContent(building.info); infoWindow.open(map, marker); }) // Automatically center the map fitting all markers on the screen map.fitBounds(bounds); }) }) 

Aggiungere un marker nel tuo programma è molto semplice. Potresti semplicemente aggiungere questo codice:

 var marker = new google.maps.Marker({ position: myLatLng, map: map, title: 'Hello World!' }); 

I seguenti campi sono particolarmente importanti e comunemente impostati quando costruisci un marcatore:

  • position (required) specifica un LatLng che identifica la posizione iniziale del marker. Un modo per recuperare un LatLng è utilizzare il servizio Geocoding.
  • map (opzionale) specifica la mappa su cui posizionare il marker. Se non si specifica una mappa sulla costruzione del marcatore, il marcatore viene creato ma non è collegato (o visualizzato sulla) mappa. Puoi aggiungere il marcatore in un secondo momento chiamando il metodo setMap() .

Nota , nell’esempio, il campo del titolo imposta il titolo del marcatore che apparirà come suggerimento.

Puoi consultare la documentazione di Google API qui .


Questo è un esempio completo per impostare un marcatore in una mappa. Stai YOUR_API_KEY , devi sostituire YOUR_API_KEY con la tua chiave API di Google :

 < !DOCTYPE html>     Simple markers    


Ora, se vuoi tracciare marcatori di un array in una mappa, dovresti fare così:

 var locations = [ ['Bondi Beach', -33.890542, 151.274856, 4], ['Coogee Beach', -33.923036, 151.259052, 5], ['Cronulla Beach', -34.028249, 151.157507, 3], ['Manly Beach', -33.80010128657071, 151.28747820854187, 2], ['Maroubra Beach', -33.950198, 151.259302, 1] ]; function initMap() { var myLatLng = {lat: -33.90, lng: 151.16}; var map = new google.maps.Map(document.getElementById('map'), { zoom: 10, center: myLatLng }); var count; for (count = 0; count < locations.length; count++) { new google.maps.Marker({ position: new google.maps.LatLng(locations[count][1], locations[count][2]), map: map, title: locations[count][0] }); } } 

Questo esempio mi dà il seguente risultato:

inserisci la descrizione dell'immagine qui


Puoi, inoltre, aggiungere una infoWindow nel tuo pin. Hai solo bisogno di questo codice:

 var marker = new google.maps.Marker({ position: new google.maps.LatLng(locations[count][1], locations[count][2]), map: map }); marker.info = new google.maps.InfoWindow({ content: 'Hello World!' }); 

Puoi avere la documentazione di Google su infoWindows qui .


Ora, possiamo aprire infoWindow quando il marker è "clik" in questo modo:

 var marker = new google.maps.Marker({ position: new google.maps.LatLng(locations[count][1], locations[count][2]), map: map }); marker.info = new google.maps.InfoWindow({ content: locations [count][0] }); google.maps.event.addListener(marker, 'click', function() { // this = marker var marker_map = this.getMap(); this.info.open(marker_map, this); // Note: If you call open() without passing a marker, the InfoWindow will use the position specified upon construction through the InfoWindowOptions object literal. }); 

Nota , puoi avere della documentazione su Listener qui nello sviluppatore google.


Infine, possiamo tracciare un'informazione in un indicatore se l'utente fa clic su di esso. Questo è il mio codice completo:

 < !DOCTYPE html>     Info windows    

Normalmente, dovresti avere questo risultato:

Il tuo risultato

Seguendo la risposta di Daniel Vassallo , ecco una versione che tratta il problema della chiusura in un modo più semplice.

Dato che tutti i marcatori avranno una singola InfoWindow e poiché JavaScript non interessa se aggiungi proprietà extra a un object, tutto ciò che devi fare è aggiungere una Finestra Info alle proprietà dell’indicatore e quindi chiamare il .open() su InfoWindow da si!

Modifica: Con un numero sufficiente di dati, il pageload potrebbe richiedere molto tempo, quindi piuttosto che build la finestra di informazioni con il marcatore, la costruzione dovrebbe avvenire solo quando necessario. Si noti che tutti i dati utilizzati per build InfoWindow devono essere aggiunti al Marker come proprietà ( data ). Si noti inoltre che dopo il primo evento click, infoWindow persisterà come proprietà del suo marker in modo che il browser non debba ribuild costantemente.

 var locations = [ ['Bondi Beach', -33.890542, 151.274856, 4], ['Coogee Beach', -33.923036, 151.259052, 5], ['Cronulla Beach', -34.028249, 151.157507, 3], ['Manly Beach', -33.80010128657071, 151.28747820854187, 2], ['Maroubra Beach', -33.950198, 151.259302, 1] ]; var map = new google.maps.Map(document.getElementById('map'), { center: new google.maps.LatLng(-33.92, 151.25) }); for (i = 0; i < locations.length; i++) { marker = new google.maps.Marker({ position: new google.maps.LatLng(locations[i][1], locations[i][2]), map: map, data: { name: locations[i][0] } }); marker.addListener('click', function() { if(!this.infoWindow) { this.infoWindow = new google.maps.InfoWindow({ content: this.data.name; }); } this.infoWindow.open(map,this); }) } 

Ecco una funzione javascript di esempio quasi completa che consentirà la definizione di più marcatori in un object JSONObject.

Visualizzerà solo i marker che si trovano nei limiti della mappa.

Questo è importante, quindi non stai facendo un lavoro extra.

Puoi anche impostare un limite per i marcatori in modo da non mostrare una quantità estrema di marker (se esiste una possibilità di una cosa nel tuo utilizzo);

inoltre non visualizzerà marcatori se il centro della mappa non è cambiato più di 500 metri.
Questo è importante perché se un utente fa clic sull’indicatore e trascina accidentalmente la mappa mentre lo fa, non si desidera che la mappa ricarichi i marcatori.

Ho allegato questa funzione al listener di eventi inattivi per la mappa in modo che gli indicatori vengano visualizzati solo quando la mappa è intriggers e visualizzeranno nuovamente i marcatori dopo un evento diverso.

Nella schermata di azione c’è un piccolo cambiamento nella schermata che mostra più contenuti nella finestra di apertura. inserisci la descrizione dell'immagine qui incollato da pastbin.com