Подтвердить что ты не робот

Как взаимодействовать с слоем маркера листка извне карты?

У меня есть карта с лифтом, показывающая точки для предметов публичного искусства, сделанные из GeoJSON. Рядом с картой я создал список фрагментов из тех же GeoJSON данных и хочу иметь возможность щелкнуть элемент из список за пределами карты, и на карте появится соответствующее всплывающее окно маркера.

Как связать список элементов с соответствующими маркерами через событие click?

Мой файл map.js выглядит следующим образом:

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)
}
4b9b3361

Ответ 1

Феликс Клинг прав, но я немного расскажу о его комментарии...

Так как L.LayerGroup и L.FeatureGroup(из которых L.GeoJSON продолжается) не имеют методов для извлечения отдельных слоев, вам нужно либо простираться от L.GeoJSON, либо добавить такой метод или сохранить свое собственное отдельное отображение из уникальный идентификатор CircleMarker от GeoJSON.

GeoJSON не требует уникального идентификатора, но я предполагаю, что маркеры в вашем фиде имеют уникальный идентификационный атрибут, называемый "id". Вам нужно будет добавить этот уникальный идентификатор к ссылкам, которые пользователь может щелкнуть, чтобы ссылки могли выбрать правильный маркер на карте. Затем вам нужно будет сохранить карту идентификаторов для маркеров, чтобы получить маркер, чтобы выбрать его на карте.

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

Вам нужно создать маркерную карту, когда вы получите данные с сервера. Ваш метод pointToLayer может быть изменен для этого:

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

Ответ 2

Я знаю, что это старый вопрос, но Лифлет на этом пути, чтобы обеспечить встроенное решение, и есть (несколько) встроенный способ достичь этого сейчас...

В этом подходе будет использоваться интерфейс layerGroup. Он предоставляет метод getLayer, который звучит так, будто было бы идеально, чтобы наши маркеры использовали идентификатор. Однако в настоящее время Лифлет не выполняет не, чтобы указать какой-либо пользовательский идентификатор или имя.

Этот issue в Github обсуждает, как это должно быть сделано. С учетом сказанного вы можете получить и сохранить автоматически сгенерированный идентификатор любого маркера (или iLayer, если на то пошло):

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

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

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

Теперь, когда мы имеем каждый идентификатор маркера, сохраненный с каждым объектом поддержки в нашем массиве данных, мы можем легко получить маркер позже так:

group.getLayer(person.marker_id)

Смотрите это перо для полного примера и этот вопрос для получения дополнительных параметров...