Search code examples
javascriptrleaflet

Add opacity slider in R leaflet


How can I add an slider in a R leaflet app, which controls the opacity of a specific layer? For this application, I don't want to use shiny (suggested here: adding sliders in R leaflet app), since it has to be exported to a stand-alone html page.

In the following example, I have two CartoDB layers for which I want to control the opacity for one of them, say the basemap layer.

Leaflet.js - Set Opacity to LayerGroup with Slider contains useful information how to add such a slider. Also, I found out that the htmlwidgets::onRender function can be used to add JavaScript code to an htmlwidget.

So I tried to following code, which doesn't work. The slider is visible, but is doesn't do anything. Moreover, the map pans when dragging the slider.

library(leaflet)
leaflet() %>% 
  addProviderTiles(provider = "CartoDB.PositronNoLabels", group="Basemap", layerId = 123) %>% 
  addTiles("http://{s}.basemaps.cartocdn.com/light_only_labels/{z}/{x}/{y}.png", group="Labels") %>% 
  addLayersControl(baseGroups="Basemap", overlayGroups = "Labels") %>% 
  addControl(html="<input id=\"slide\" type=\"range\" min=\"0\" max=\"1\" step=\"0.1\" value=\"1\" onchange=\"updateOpacity(this.value)\">") %>%
  onRender("
     function updateOpacity(value) {
         this.getLayer(123).opacity(value);
     }
  ")

Anyone who can help me out? Thanks in advance!


Solution

  • This one was tricky, and I will confess that I am not sure my solution below is the proper way to handle, but it does work for me.

    library(leaflet)
    
    leaflet() %>% 
      addProviderTiles(provider = "CartoDB.PositronNoLabels", 
                       group = "Basemap",
                       layerId = 123) %>% 
      addTiles("http://{s}.basemaps.cartocdn.com/light_only_labels/{z}/{x}/{y}.png",
               group = "Labels") %>% 
      addLayersControl(baseGroups = "Basemap",
                       overlayGroups = "Labels") %>% 
      addControl(html = "<input id=\"slide\" type=\"range\" min=\"0\" max=\"1\" step=\"0.1\" value=\"1\">") %>%
      onRender("function(el,x,data){
                         var map = this;
                         var evthandler = function(e){
                            var labels = map.layerManager._byGroup.Labels;
                            Object.keys(labels).forEach(function(el){
                                 labels[el]._container.style.opacity = +e.target.value;
                                 });
                         };
                  $('#slide').on('mousemove',L.DomEvent.stopPropagation);
                  $('#slide').on('input', evthandler);
                  }
              ")