Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to switch between multiple legends when switching between base groups?

I am visualizing some vector data using leaflet in r which has multiple non-spatial variables that a user might be interested in. I want to allow the user to select one variable that will determine the color of the features. I accomplish this with the baseGroups argument to the addLayersControl function, where each group is the same data with a different color palette. This works fine for switching the colors of the features themselves, but does not allow me to switch between legends- every legend I add is always shown, even if I use the appropriate group within addLegend. See the example code and screenshot below:

data <- data.frame(long = c(-93.2, -93, -93.5), lat = c(44.9, 45, 44.9), 
               var1 = c(1,2,3), var2 = c(10, 9, 1))

pal1 <- colorNumeric(palette = "Blues", domain = data$var1)
pal2 <- colorNumeric(palette = "Reds", domain = data$var2)

leaflet(data) %>%
  addCircleMarkers(color = ~pal1(var1), group = "var1") %>%
  addCircleMarkers(color = ~pal2(var2), group = "var2") %>%
  addLegend(pal = pal1, values = ~var1, group = "var1") %>%
  addLegend(pal = pal2, values = ~var2, group = "var2") %>%
  addLayersControl(baseGroups = c("var1", "var2"), position = "topleft")

If I replace baseGroups with overlayGroups in my layers control, this works as expected, and only the legends for the selected groups are shown. However, this option isn't ideal because I don't want the user to be able to select multiple groups or deselect all groups.

enter image description here

These questions are quite similar to mine, but the accepted solutions both use overlayGroups, while I want to stick with baseGroups. I'm also hoping to avoid using shiny, if possible.

like image 543
Joe Avatar asked Sep 18 '18 19:09

Joe


Video Answer


1 Answers

It seems legends in baseGroups won't remove/re-added as if in overlayGroups, which can be further proved by the persistence of legends even after calling hideGroup("var1").

A crude workaround can be adding an event handler to hide/unhide legends according to the current selected group of baseGroups using group = "<groupName>" as a key, and nothing else should need to be changed. For example:

htmlwidgets::onRender("
    function(el, x) {
      var updateLegend = function () {
          var selectedGroup = document.querySelectorAll('input:checked')[0].nextSibling.innerText.substr(1);

          document.querySelectorAll('.legend').forEach(a => a.hidden=true);
          document.querySelectorAll('.legend').forEach(l => {
            if (l.children[0].children[0].innerText == selectedGroup) l.hidden=false;
          });
      };
      updateLegend();
      this.on('baselayerchange', e => updateLegend());
    }")

Demo

demo of workaround

Source of Demo

require(leaflet)


data <- data.frame(long = c(-93.2, -93, -93.5), lat = c(44.9, 45, 44.9), 
                   var1 = c(1,2,3), var2 = c(10, 9, 1))

pal1 <- colorNumeric(palette = "Blues", domain = data$var1)
pal2 <- colorNumeric(palette = "Reds", domain = data$var2)

leaflet(data) %>%
  addCircleMarkers(color = ~pal1(var1), group = "var1") %>%
  addCircleMarkers(color = ~pal2(var2), group = "var2") %>%
  addLegend(pal = pal1, values = ~var1, group = "var1") %>%
  addLegend(pal = pal2, values = ~var2, group = "var2") %>%
  addLayersControl(baseGroups = c("var1", "var2"), 
                   position = "topleft",
                   options = layersControlOptions(collapsed=F)) %>%
  htmlwidgets::onRender("
    function(el, x) {
      var updateLegend = function () {
          var selectedGroup = document.querySelectorAll('input:checked')[0].nextSibling.innerText.substr(1);

          document.querySelectorAll('.legend').forEach(a => a.hidden=true);
          document.querySelectorAll('.legend').forEach(l => {
            if (l.children[0].children[0].innerText == selectedGroup) l.hidden=false;
          });
      };
      updateLegend();
      this.on('baselayerchange', e => updateLegend());
    }")
like image 151
Quar Avatar answered Oct 18 '22 03:10

Quar