Leaflet Layer Control: динамическое добавление и удаление элементов управления слоями

avatar
IrfanClemson
1 июля 2021 в 18:15
642
2
0

Я пытаюсь добавить управление слоями в библиотеку Javascript Leaflet; для справки см. это: https://leafletjs.com/reference-1.7.1.html#control-layers. Мой код по большей части работает нормально: у меня есть объект layerControl, который инициализируется baseLayers, но пока нет наложения. Затем я добавляю наложение layer_USA_Counties, как показано в коде ниже. Пока все хорошо.

Но мне нужна возможность добавить новое наложение isochronesGroup к объекту layerControl. Этот код работает нормально, за исключением того, что в последующих исполнениях кода isochronesGroup продолжает добавлять элементы управления — см. этот снимок экрана. Я могу удалить элемент управления с помощью закомментированной команды, но она, конечно же, также удалит все элементы управления isochronesGroup, поэтому он вообще не будет отображаться. Обратите внимание: загруженные слои и их элементы управления не обязательно должны иметь тип layerGroup().

enter image description here

//globally set
var baseLayers = {
        "Grayscale": grayscale,
        "Streets": streets
 };     
layerControl = L.control.layers(baseLayers, null, { collapsed: false }).addTo(map);

//add a layer from a WMS call and add to the layerControl object
map_LayerGroup = L.layerGroup().addLayer(layer_USA_Counties);///.addTo(map);   
layerControl.addOverlay(map_LayerGroup, "USA Counties");

//Following code gets executed again and again based on user interaction        
isochronesGroup = L.layerGroup().addLayer(route_lines).addTo(map);
layerControl.addOverlay(isochronesGroup, "Isochrones");
///layerControl.removeLayer(isochronesGroup); //WORKS If already created. Or errors
Источник

Ответы (2)

avatar
JRI
2 июля 2021 в 12:26
0

Вы сможете сделать это без необходимости каждый раз заново создавать элемент управления. Проблема в том, что isochronesGroup LayerGroup создается заново, что означает, что вы теряете след слоев, которые уже были добавлены в элемент управления. Попробуйте выполнить этот пример в консоли браузера:

.
layerControl = L.control.layers(baseLayers, null, {collapsed: false}).addTo(map);

isochronesGroup = L.layerGroup().addLayer(route_lines).addTo(map);
layerControl.addOverlay(isochronesGroup, "I1");    // Adds I1
layerControl.addOverlay(isochronesGroup, "I2");    // Adds I2
layerControl.removeLayer(isochronesGroup);         // Removes I1
layerControl.removeLayer(isochronesGroup);         // Removes I2
layerControl.removeLayer(isochronesGroup);         // No effect (and no error)
layerControl.removeLayer(wibble);                  // Error

Вы должны увидеть, что хотя вы получаете повторяющиеся записи в элементе управления слоями, повторные вызовы removeLayer() в конечном итоге удаляют их все. Это работает, потому что переменная isochronesGroup все время ссылается на один и тот же объект. Вызвать removeLayer() в дополнительное время не проблема, даже если все слои удалены из элемента управления, если isochronesGroup фактически определен как допустимый слой. Теперь попробуйте следующее:

layerControl = L.control.layers(baseLayers, null, {collapsed: false}).addTo(map);

isochronesGroup = L.layerGroup().addLayer(route_lines).addTo(map);
layerControl.addOverlay(isochronesGroup, "I1");    // Adds I1
isochronesGroup = L.layerGroup().addLayer(route_lines).addTo(map);
layerControl.addOverlay(isochronesGroup, "I2");    // Adds I2
layerControl.removeLayer(isochronesGroup);         // Removes I2
layerControl.removeLayer(isochronesGroup);         // No effect
layerControl.removeLayer(isochronesGroup);         // No effect

В приведенном выше примере I2 удаляется из управления, но I1 остается. Это связано с тем, что isochronesGroup был переопределен и теперь является объектом, отличным от того, который был добавлен к элементу управления с меткой I1.

Учитывая вышеизложенное, вот еще два элегантных способа обойти вашу проблему:

  1. Когда вам нужно создать новый слой isochronesGroup, немедленно удалите старый из управления слоями, пока переменная isochronesGroup по-прежнему ссылается на старый объект слоя.

  2. Вместо того, чтобы каждый раз переопределять isochronesGroup LayerGroup, повторно используйте объект, но используйте clearLayers(), removeLayer() и addLayer(), чтобы изменить содержащиеся в нем слои.

При использовании второго подхода вам не нужно постоянно менять элемент управления слоями. например

// Initialisation
isochronesGroup = L.layerGroup().addTo(map);           // Create empty LayerGroup
layerControl.addOverlay(isochronesGroup, "Isochrones");  // Add group to control

// Code to call repeatedly
isochronesGroup.clearLayers().addLayer(route_lines);
IrfanClemson
3 июля 2021 в 11:36
0

Здравствуйте, спасибо, сэр! Я попробовал ваше предложение «второго подхода», но получил ошибку «TypeError: layerControl.addLayer не является ошибкой функции». Я думаю, что я должен придерживаться того, что у меня есть на данный момент. Спасибо еще раз.

JRI
3 июля 2021 в 13:21
0

Извините моя ошибка. Этот addLayer() должен был быть addOverlay(). Я отредактировал свой ответ соответственно.

IrfanClemson
6 июля 2021 в 12:06
0

Привет, спасибо за постоянную помощь и поддержку! Поэтому я реализовал правильный блок кода «второй подход», как указано выше, и ошибка исчезла, но первоначальная проблема с постоянным добавлением параметров изохрон вернулась.

avatar
IrfanClemson
1 июля 2021 в 18:51
0

Вот что я в итоге сделал. Это хак, но работает. Позже я сделаю это как часть некоторой функции обслуживания, чтобы добавить/удалить параметры элемента управления по мере необходимости. Код в Вопросе остается прежним, за исключением того, что изменилась следующая часть. По сути, я воссоздаю Control.

ХТХ

//Following code gets executed again and again based on user interaction
//Remove the control entirely! 
layerControl.remove();
//Add the control back with baseLayers
layerControl = L.control.layers(baseLayers, null, { collapsed: false }).addTo(map);
//Add back the USA Counties Overlay Control
usa_counties_LayerGroup = L.layerGroup().addLayer(layer_USA_Counties);///.addTo(map); 
layerControl.addOverlay(usa_counties_LayerGroup, "USA Counties");
//Add the isochronesGroup Overlay Control
isochronesGroup = L.layerGroup().addLayer(route_lines).addTo(map);
layerControl.addOverlay(isochronesGroup, "Isochrones");