2012-10-22 4 views
26

Ho una mappa illustrativa che mostra i punti per i pezzi di arte pubblica, resi da GeoJSON. Accanto alla mappa, ho creato un elenco dei pezzi degli stessi dati GeoJSON e voglio poter fare clic su un elemento dall'elenco all'esterno della mappa e visualizzare il popup del relativo marker sulla mappa.Come interagire con il livello del marker di volantini dall'esterno della mappa?

Come posso collegare l'elenco degli articoli ai rispettivi indicatori tramite un evento click?

Il mio file map.js assomiglia a questo:

var map; 
var pointsLayer; 

$(document).ready(function() { 
    map = new L.Map('mapContainer'); 
    var url = 'http://{s}.tiles.mapbox.com/v3/mapbox.mapbox-streets/{z}/{x}/{y}.png'; 
    var copyright = 'Map data © 2011 OpenStreetMap contributors, Imagery © 2011 CloudMade'; 
    var tileLayer = new L.TileLayer(url, { 
     attribution: copyright 
    }); 
    var startPosition = new L.LatLng(41.883333, - 87.633333); 
    map.on('load', function (e) { 
     requestUpdatedPoints(e.target.getBounds()) 
    }); 
    map.setView(startPosition, 13).addLayer(tileLayer); 
    map.on('moveend', function (e) { 
     requestUpdatedPoints(e.target.getBounds()) 
    }) 
}); 

function requestUpdatedPoints(bounds) { 
    $.ajax({ 
     type: 'GET', 
     url: '/SeeAll', 
     dataType: 'json', 
     data: JSON.stringify(bounds), 
     contentType: 'application/json; charset=utf-8', 
     success: function (result) { 
      parseNewPoints(result); 
      addToList(result) 
     }, 
     error: function (req, status, error) { 
      alert('what happen? did you lose conn. to server ?') 
     } 
    }) 
} 

function addToList(data) { 
    for (var i = 0; i < data.features.length; i++) { 
     var art = data.features[i]; 
     $('div#infoContainer').append('<a href="#" class="list-link" title="' + art.properties.descfin + '"><div class="info-list-item">' + '<div class="info-list-txt">' + '<div class="title">' + art.properties.wrknm + '</div>' + '<br />' + art.properties.location + '</div>' + '<div class="info-list-img">' + art.properties.img_src + '</div>' + '<br />' + '</div></a>') 
    } 
    $('a.list-link').click(function (e) { 
     alert('now you see what happens when you click a list item!'); 
     e.preventDefault() 
    }) 
} 

function parseNewPoints(data) { 
    if (pointsLayer != undefined) { 
     map.removeLayer(pointsLayer) 
    } 
    pointsLayer = new L.GeoJSON(); 
    var geojsonMarkerOptions = { 
     radius: 8, 
     fillColor: "#FF6788", 
     color: "YELLOW", 
     weight: 1, 
     opacity: 1, 
     fillOpacity: 0.5 
    }; 
    L.geoJson(data, { 
     pointToLayer: function (feature, latlng) { 
      return L.circleMarker(latlng, geojsonMarkerOptions) 
     }, 
     onEachFeature: function (feature, pointsLayer) { 
      pointsLayer.bindPopup(feature.properties.img_src + "<br />" + feature.properties.wrknm + "<br />" + feature.properties.artist + "<br />" + feature.properties.location + '<div class="description">' + feature.properties.descfin + '</div>') 
     } 
    }).addTo(map) 
} 
+1

vorrei creare un hash mappa 'identi fier -> marker' e quindi cerca l'indicatore per ID quando fai clic su un elemento. –

risposta

35

Felix Kling è giusto, ma io espandere il suo commento un po '...

Dal L.LayerGroup e L.FeatureGroup (da cui si estende L.GeoJSON) non hanno metodi per recuperare i singoli layer che dovrai estendere da L.GeoJSON e aggiungere un tale metodo o mantenere la tua mappatura separata dall'ID univoco a CircleMarker da GeoJSON.

GeoJSON non richiede un ID univoco, ma presumo che i marcatori nel feed abbiano un attributo ID univoco chiamato "id". Sarà necessario aggiungere questo ID univoco ai collegamenti su cui l'utente può fare clic in modo che i collegamenti possano selezionare l'indicatore giusto sulla mappa. Quindi dovrai memorizzare una mappa di identificativi in ​​marcatori per recuperare l'indicatore per selezionarlo sulla mappa.

markerMap = {}; // a global variable unless you extend L.GeoJSON 

// Add the marker id as a data item (called "data-artId") to the "a" element 
function addToList(data) { 
    for (var i = 0; i < data.features.length; i++) { 
     var art = data.features[i]; 
     $('div#infoContainer').append('<a href="#" class="list-link" data-artId=\"'+art.id+'\" title="' + art.properties.descfin + '"><div class="info-list-item">' + '<div class="info-list-txt">' + '<div class="title">' + art.properties.wrknm + '</div>' + '<br />' + art.properties.location + '</div>' + '<div class="info-list-img">' + art.properties.img_src + '</div>' + '<br />' + '</div></a>') 
    } 
    $('a.list-link').click(function (e) { 
     alert('now you see what happens when you click a list item!'); 

     //Get the id of the element clicked 
     var artId = $(this).data('artId'); 
     var marker = markerMap[artId]; 

     //since you're using CircleMarkers the OpenPopup method requires 
     //a latlng so I'll just use the center of the circle 
     marker.openPopup(marker.getLatLng()); 
     e.preventDefault() 
    }) 
} 

È necessario creare il markerMap quando si ricevono i dati dal server. Il tuo metodo pointToLayer potrebbe essere modificato per farlo:

L.geoJson(data, { 
    pointToLayer: function (feature, latlng) { 
     var marker = new L.CircleMarker(latlng, geojsonMarkerOptions); 
     markerMap[feature.id] = marker; 
     return marker; 
    },... 
+1

questa è una spiegazione molto utile. Grazie per aver dedicato del tempo. – roy

+3

Mi chiedo se c'è un modo più semplice per farlo con l'ultima versione di LeafletJS. – fuzz

+0

So che è molto tardi, ma ho aggiunto una risposta qui sotto, usando i metodi dell'ultima versione di Leaflet, per ottenere la stessa cosa. –

4

So che questa è una domanda più vecchio ma opuscolo è on it's way a fornire una soluzione integrata e v'è una (un po ') built-in modo per raggiungerlo ora ...

L'approccio sarebbe utilizzare l'interfaccia layerGroup. Fornisce un metodo, getLayer, che suona come sarebbe perfetto ottenere i nostri marcatori utilizzando un ID. Tuttavia, al momento, il volantino non fornisce un modo per specificare un ID o un nome personalizzato.

Questo issue su Github illustra come dovrebbe essere fatto. Detto questo, è possibile ottenere e salvare l'ID di auto-generata per ogni marcatore (o iLayer per questo) in questo modo:

let people = [...], 
    group = L.layerGroup() 

people.forEach(person => { 
    let marker = // ... create marker 

    group.addLayer(marker); 
    person.marker_id = group.getLayerId(marker) 
}) 

Ora che abbiamo ID di ogni marcatore salvata con ogni oggetto appoggio nella nostra gamma dei dati si può facilmente ottenere il marcatore più avanti in questo modo:

group.getLayer(person.marker_id) 

Vedi this pen per un esempio completo e this question per ulteriori opzioni ...