web-dev-qa-db-fra.com

Comment interagir avec la couche marqueur de foliole depuis l'extérieur de la carte?

J'ai une carte de dépliant montrant les points pour les pièces d'art public, rendue à partir de GeoJSON . À côté de la carte, j'ai créé une liste des pièces à partir des mêmes données GeoJSON et je veux pouvoir cliquer sur un élément de la liste en dehors de la carte et faire apparaître la fenêtre contextuelle du marqueur associé. la carte.

Comment puis-je lier la liste des éléments à leurs marqueurs respectifs via un événement de clic?

Mon fichier map.js ressemble à ceci:

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)
}
29
roy

Felix Kling a raison mais je vais développer un peu son commentaire ...

Étant donné que L.LayerGroup et L.FeatureGroup (dont L.GeoJSON s'étend) ne disposent pas de méthodes pour récupérer des couches individuelles, vous devrez soit étendre à partir de L.GeoJSON et ajouter une telle méthode, soit conserver votre propre mappage distinct d'un ID unique à CircleMarker de GeoJSON.

GeoJSON ne nécessite pas d'ID unique, mais je suppose que les marqueurs de votre flux ont un attribut d'ID unique appelé "id". Vous devrez ajouter cet ID unique aux liens sur lesquels l'utilisateur peut cliquer afin que les liens puissent sélectionner le bon marqueur sur la carte. Ensuite, vous devrez stocker une carte d'identifiants pour les marqueurs afin de récupérer le marqueur pour le sélectionner sur la carte.

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

Vous devez créer le markerMap lorsque vous obtenez les données du serveur. Votre méthode pointToLayer pourrait être modifiée pour ce faire:

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

Je sais que c'est une question plus ancienne, mais Leaflet est en route pour fournir une solution intégrée et il existe (un peu) une méthode intégrée pour y parvenir maintenant ...

L'approche serait d'utiliser l'interface layerGroup. Il fournit une méthode, getLayer, qui sonne comme si ce serait parfait d'obtenir nos marqueurs en utilisant un ID. Cependant, pour le moment, Leaflet ( ne fournit aucun moyen de spécifier un ID ou un nom personnalisé.

Cette issue sur Github explique comment cela doit être fait. Cela dit, vous pouvez obtenir et enregistrer l'ID généré automatiquement de n'importe quel marqueur (ou iLayer d'ailleurs) comme ceci:

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

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

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

Maintenant que nous avons enregistré chaque ID de marqueur avec chaque objet de support dans notre tableau de données, nous pouvons facilement obtenir le marqueur plus tard comme suit:

group.getLayer(person.marker_id)

Voir ce stylo pour un exemple complet et cette question pour plus d'options ...

5
Skip Jack