2016-07-10 18 views
2

Ich habe eine Karte mit mehreren Polygonen gerendert, die sich überlappen können. Ich verwende leafletPip.pointInLayer (Punkt, Layer) von https://github.com/mapbox/leaflet-pip für die Bestimmung, welche Polygone überlappen. Dies geschieht in der processClick Funktion. Im Vue-Objekt erstelle ich die Karte und meine GeoJSON-Ebene mit den Polygonen. Was ich jetzt möchte, ist folgende Funktion: Wenn Sie auf einen Punkt auf der Karte klicken und dieser Punkt in mehreren Polygonen enthalten ist, haben Sie so etwas wie ein Auswahlwerkzeug, z. Klicken Sie in einem Popup auf eines dieser Polygone und lösen Sie die .on ('click') Funktion nur für dieses spezielle Polygon aus. Ich habe alle Leaflet-Funktionen durchsucht, aber ich konnte nichts wirklich Nützliches finden. Wenn Sie jetzt auf einen Punkt klicken, der in mehreren Polygonen enthalten ist, lösen Sie nur das .on ("Klicken") für das Polygon aus, das die anderen räumlich enthält.Wählen Sie eine Funktion aus mehreren überlappenden Features (hier Polygone) auf einer Leaflet Map

var mapVue = new Vue({ 
    parent: vue_broadcaster, 
    el: '#map', 
    data: { 
    map: null, 
    layer: null 
    }, 
    created: function() { 
    // Adding Leaflet map here 
    var map = L.map('map').setView([51.959, 7.623], 14); 
    L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', { 
     attribution: '&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors' 
    }).addTo(map); 
    this.$set('map', map); 
    this.get_zones(); 
    }, 
    methods: { 
    switch_zone: function (zoneid) { 
     this.$dispatch('zoneSelected', zoneid) 
    }, 
    get_zones: function() { 
     this.$http.get('/api/zones/', function (data) { 
     // Creation of the GeoJSON layer 
     var geoZone = { 
      "type": "FeatureCollection", 
      "features": [] 
     }; 
     for (var i = 0; i < data['Zones'].length; i++) { 
      geoZone.features.push({ 
      "type": "Feature", 
      "geometry": { 
       "type": "Polygon", 
       "coordinates": [[]] 
      }, 
      "properties": { 
       "name": "" 
      } 
      }) 
      geoZone.features[i].properties.name = data['Zones'][i]['Name']; 
      for (var j = 0; j < data['Zones'][i]['Geometry']['Coordinates'].length; j++) { 
      geoZone.features[i].geometry.coordinates[0].push([data['Zones'][i]['Geometry']['Coordinates'][j][1], data['Zones'][i]['Geometry']['Coordinates'][j][0]]) 
      } 
      this.layer = new L.geoJson(geoZone) 
      .bindPopup(data['Zones'][i]['Name']) 
      .on('click', dispatchZoneID(data['Zones'][i]['Zone-id'], this)) 
      .on('click', function (e) { 
       processClick(e.latlng.lat, e.latlng.lng) 
      }) 
      .addTo(this.map) 
     }; 
     }) 
    } 
    } 
}); 
// function for processing the clicks on the map 
function processClick(lat, lng) { 
    var info = ''; 
    var point = [lng, lat]; 
    var match = leafletPip.pointInLayer(point, mapVue.layer, false); 
    if (match.length) { 
    for (var i = 0; i < match.length; i++) { 
     info += 
     "<b>" + match[i].feature.properties.name + "<br>" 
    } 
    } 
    if (info) { 
    mapVue.map.openPopup(info, [lat, lng]); 
    } 
}; 
// not important for this one 
function dispatchZoneID(id, vue) { 
    return function() { 
    vue.$dispatch('zoneSelected', id) 
    } 
}; 

Antwort

1

Ich fand eine Lösung für mich, aber es ist vielleicht nicht die eleganteste. Wenn der angeklickte Punkt in mehreren Polygonen (match.length> 1) enthalten ist, erzeuge ich diesen info String. In jeder Iteration erstellt die for-Schleife eine anklickbare Verbindung, die dann je nach der ID eine Funktion auf Klick aufruft. Also muss ich im Grunde eine Menge HTML in einer einzigen Zeichenfolge generieren und mit Literalen und String-Verkettungen arbeiten. Dann rufe ich die openPopup Funktion mit info als meine HTML-Param.

function processClick(lat, lng) { 
    var info = ''; 
    var point = [lng, lat]; 
    var match = leafletPip.pointInLayer(point, mapVue.layer, false); 
    if (match.length > 1) { 
    for (var i = 0; i < match.length; i++) { 
     id = match[i].feature.properties.zoneid; 
     name = match[i].feature.properties.name; 
     info += 
     "<b><a onclick='dispatchZoneID(\"" + id + "\")();'>"+ name + "</a><br>" 
    } 
    } 
    else dispatchZoneID(mapVue.zoneid)(); 

    if (info) { 
    mapVue.map.openPopup(info, [lat, lng]); 
    } 
}; 
+1

Ich sehe nichts falsch in Ihrem Ansatz. Vielleicht könnten Sie Elemente mit Dataset generieren und ihnen Ereignis-Listener anhängen, anstatt einen HTML-String mit einem Inline-Onclick zu verwenden, aber Sie würden wahrscheinlich mehr Code benötigen. – ghybs

+0

Was genau meinst du mit "Elemente mit Dataset erzeugen"? – Flugmango

+0

Etwas wie 'var p = document.createElement (" p "); p.dataset.zoneid = id; p.addEventListener (fnDispatch); ' – ghybs