Назначить идентификатор маркеру в листовке
Итак, я пытаюсь достичь результата, как на четырехквартале: https://foursquare.com/explore?cat=drinks&mode=url&near=Paris, который, когда вы clik на маркере на карте, прокручивает через перечисленные рестораны на правой стороне экрана в специальный ресторан, и выделяет его через CSS. И наоборот, когда вы нажимаете на ресторан в списке, он выделяет его на карте.
Я использую skobbler/листовки. Я думаю, что могу добиться этого, изменив динамически CSS, как показано в этом примере: http://jsfiddle.net/gU4sw/7/ + прокрутка к пункту назначения script уже установлена в страница.
Чтобы достичь этого, похоже, мне нужно назначить идентификатор в маркерах (2 маркера ниже):
var marker = L.marker([52.52112, 13.40554]).addTo(map);
marker.bindPopup("Hello world!<br>I am a popup1.", { offset: new L.Point(-1, -41) }).openPopup();
var marker = L.marker([52.53552, 13.41994]).addTo(map);
marker.bindPopup("Hello world!<br>I am a popup2.", { offset: new L.Point(-1, -41) }).openPopup();
Вопрос: как я могу назначить идентификатор маркера для запуска изменения css в соответствующем элементе на моей странице html?
Мои знания о JS очень ограничены, но может быть там приятное и легкое решение, спасибо
Ответы
Ответ 1
Я искал хороший способ сделать это, и насколько я могу судить, до сих пор нет встроенного способа (с помощью листовки), чтобы дать маркеру идентификатор. Я знаю, что немного опоздал, чтобы ответить на это, но, надеюсь, это поможет другим, которые спотыкаются на этот вопрос. Насколько я могу судить, здесь есть две основные проблемы:
Проблема № 1:
Если вы не сохраните свои маркеры на объекте или карте, описанном ниже, нет более простого программного доступа к ним позже. Например - пользователь нажимает что-то ВНЕ ВИДА карту, соответствующую маркеру ВНУТРИ карты.
Проблема № 2:
Когда пользователь нажимает на маркер ВНУТРИ карты, нет встроенного способа получить идентификатор этого маркера, а затем использовать его, чтобы выделить соответствующий элемент или вызвать действие ВНЕ ВИДА карты.
Решение
Использование одного или нескольких из этих параметров поможет устранить проблемы, описанные выше. Я начну с того, о котором говорилось в предыдущем ответе. Вот рабочая пера, в которой содержится весь код, найденный ниже.
Вариант №1:
Сохраните каждый маркер, используя жесткий код или динамический идентификатор, внутри объекта -
// Create or retrieve the data
var data = [
{
name: 'Bob',
latLng: [41.028, 28.975],
id: '2342fc7'
}, {...}, {...}
];
// Add an object to save markers
var markers = {};
// Loop through the data
for (var i = 0; i < data.length; i++) {
var person = data[i];
// Create and save a reference to each marker
markers[person.id] = L.marker(person.latLng, {
...
}).addTo(map);
}
Как и в случае с другим ответом, вы можете получить доступ к одному маркеру, используя -
var marker = markers.2342fc7; // or markers['2342fc7']
Вариант № 2:
В листовке не предусмотрена встроенная опция "id" для маркеров, вы можете добавить идентификатор к элементу напрямую, обратившись к свойству ._icon
:
// Create and save a reference to each marker
markers[person.id] = L.marker(person.latLng, {...}).addTo(map);
// Add the ID
markers[person.id]._icon.id = person.id;
Теперь, когда вы обрабатываете события щелчка, легко, как пирог, получить этот идентификатор маркера:
$('.leaflet-marker-icon').on('click', function(e) {
// Use the event to find the clicked element
var el = $(e.srcElement || e.target),
id = el.attr('id');
alert('Here is the markers ID: ' + id + '. Use it as you wish.')
});
Вариант № 3:
Другим подходом будет использование интерфейса layerGroup
. Он предоставляет метод getLayer
, который звучит так, будто было бы идеально, чтобы наши маркеры использовали идентификатор. Однако в настоящее время Листовка не предоставляет никакого способа указать пользовательский идентификатор или имя. Этот issue в Github обсуждает, как это должно быть сделано. Однако вы можете получить и сохранить автоматически сгенерированный идентификатор любого маркера (или iLayer
, если на то пошло):
var group = L.layerGroup()
people.forEach(person => {
// ... create marker
group.addLayer( marker );
person.marker_id = group.getLayerId(marker)
})
Теперь, когда мы имеем каждый идентификатор маркера, сохраненный с каждым объектом поддержки в нашем массиве данных, мы можем легко получить маркер позже так:
group.getLayer(person.marker_id)
См. это перо для полного примера...
Вариант № 4:
Самый чистый способ сделать это, если у вас есть время, - это расширить класс маркеров буклета, чтобы он обрабатывал ваши индивидуальные потребности. Вы можете либо добавить id к параметрам, либо вставить собственный HTML-код в маркер, который имеет ваш id/class. Дополнительную информацию об этом см. В документации .
Вы также можете использовать circleMarker, который в path options, вы увидите вариант для классаName, который может быть приятным для групп стилей похожих маркеров.
Стайлинг:
Почти забыл, что ваш оригинальный вопрос был поставлен с целью стилизации... просто используйте идентификатор для доступа к отдельным элементам:
.leaflet-marker-icon#2342fc7 { ... }
Заключение
Я также упомянул, что слои и группы функций предоставляют еще один отличный способ взаимодействия с маркерами. Вот question, который немного обсуждается. Не стесняйтесь возиться с вилкой или второе перо и комментарий, если я что-то пропустил.
Ответ 2
Легкий способ сделать это - добавить все маркеры в список с уникальным идентификатором.
var markersObject = {};
markersObject["id1"] = marker1;
markersObject["id2"] = marker2;
markersObject["id3"] = marker3;
Если список ресторанов имеет свойство в элементе html одного ресторана, который соответствует идентификатору добавленного маркера. Что-то вроде:
<a href="#" id="singleRestaurantItem" data-restaurantID="id1" data-foo="bar">Click</a>
Затем добавьте событие click, в котором вы передадите идентификатор ресторана (в данном случае "data-restaurantID" ) и сделайте что-нибудь вроде:
markersObject["passedValueFromTheClickedElement"].openPopup();
Таким образом, как только вы нажмете на элемент в списке, откроется всплывающее окно с маркерами, указывающее, где на карте находится ресторан.
Ответ 3
var MarkerIcon = L.Icon.extend({
options: {
customId: "",
shadowUrl: 'leaf-shadow.png',
iconSize: [64, 64],
shadowSize: [50, 64],
iconAnchor: [22, 94],
shadowAnchor: [4, 62],
popupAnchor: [-3, -76]
}
});
var greenIcon = new MarkerIcon({iconUrl: "/resources/images/marker-green.png"}),
redIcon = new MarkerIcon({iconUrl: "/resources/images/marker-red.png"}),
orangeIcon = new MarkerIcon({iconUrl: "/resources/images/marker-orange.png"});
var mymap = L.map('mapid').setView([55.7522200, 37.6155600], 13);
L.tileLayer('https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token=pk.eyJ1IjoibWFwYm94IiwiYSI6ImNpejY4NXVycTA2emYycXBndHRqcmZ3N3gifQ.rJcFIG214AriISLbB6B5aw', {
maxZoom: 18,
id: 'mapbox.streets'
}).addTo(mymap);
// добавить маркер
L.marker([55.7522200, 37.6155600], {customId:"010000006148", icon: greenIcon, title:setMarkerTitle("010000006148")}).addTo(mymap).on('click', markerOnClick);
L.marker([55.7622200, 37.6155600], {customId:"010053166625", icon: redIcon, title: setMarkerTitle("010053166625")}).addTo(mymap).on('click', markerOnClick);
function markerOnClick(e) {
var customId = this.options.customId;
document.location.href = "/view/abonents/" + customId;
}
function setMarkerTitle(customId){
var result = customId;
result += "\nline2 ";
result += "\nline3 ";
return result;
}
Ответ 4
В моем случае я обнаружил, что лучшим способом было бы просто сгенерировать и передать уникальный идентификатор объекту опций L.marker
при его создании.
const newMarker = L.marker([lat, lng], {uniqueID: uniqueID})
Затем вы можете добавить этот маркер в листовку layerGroup
.
const newLayerGroup = L.layerGroup().addTo(map);
newLayerGroup.addLayer(newMarker);
Вы можете получить доступ к идентификатору с помощью layer.options.uniqueID
. Это позволит мне позже найти маркер и манипулировать им; все, что мне нужно, это Leaflet .eachLayer()
и уникальный идентификатор.
Мой бэкэнд (Cloud Firestore) уже генерирует уникальные идентификаторы документов, что позволяет очень легко синхронизировать мою карту Leaflet и бэкэнд в режиме реального времени, а не перестраивать и перемонтировать всю layerGroup или обновлять страницу.
//e.g. a callback which fires whenever a doc has been removed from my db
newLayerGroup.eachLayer((layer) => {
if (deletedDocID === layer.options.uniqueID) {
newLayerGroup.removeLayer(layer);
}
});
Ответ 5
Довольно простой и простой способ выполнить создание массива интерактивных маркеров в объекте листовой карты - это манипулировать списком классов созданного маркера, добавляя пользовательское увеличенное имя класса для каждого маркера. Тогда легко создать слушателя и узнать, какой маркер был нажат. Пропуская активную или нет, у каждого есть извлекаемое событие щелчка с надежным идентификатором.
// creates markers, each with a leaflet supplied class
if (length === 1) {
for (i = 0; i < parks.length; ++i) {
if (parks[i].parksNumber !== parks.parksNumber)
L.marker([parks[i].latitude, parks[i].longitude], {
icon: parks[i].iconMarker
}).addTo(mymap);
}
}
// select all of the leaflet supplied class
let markers = document.querySelectorAll(".leaflet-marker-icon");
// loop through those elements and first assign the indexed custom class
for (i = 0; i < markers.length; ++i) {
markers[i].classList.add("marker_" + parks[i].parksNumber);
// then add a click listener to each one
markers[i].addEventListener("click", e => {
// pull the class list
let id = String(e.target.classList);
// pull your unique ID from the list, be careful cause this list could
// change orientation, if so loop through and find it
let parksNumber = id.split(" ");
parksNumber = parksNumber[parksNumber.length - 1].replace("marker_", "");
// you have your unique identifier to then do what you want with
search_Number_input.value = parksNumber;
HandleSearch();
});
}
Ответ 6
Листовка имя_класса позволяет добавлять идентификаторы к объектам:
var onMouseover = function() {
// returns all members of the specified class
d3.selectAll(".mySpecialClass")
.style("opacity", ".1");
};
// add desired class to pointer
L.circleMarker([46.85, 2.35], {className: "mySpecialClass"})
.addTo(map).on('mouseover', onMouseover);
// to select the marker(s) with a particular class, just use css selectors
// here a d3.js solution
d3.selectAll(".mySpecialClass")
.style("opacity", ".3")