3

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!

Community
  • 1
  • 1
Martijn Tennekes
  • 1,951
  • 13
  • 19

1 Answers1

2

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);
              }
          ")
bathyscapher
  • 1,615
  • 1
  • 13
  • 18
timelyportfolio
  • 6,479
  • 30
  • 33
  • Bhaskar Karambelkar found a leaflet plugin for opacity https://twitter.com/bhaskar_vk/status/800857064847405057 that might provide a more robust solution if/when we add to leaflet.extras. – timelyportfolio Nov 22 '16 at 12:37
  • any insight as to why this functionality doesn't work inside of Shiny? I put your exact code in a basic Shiny Leaflet app and instead of toggling the opacity, dragging the slider physically pans the map window. – Lauren Jan 19 '17 at 20:56