Skip to content

Instantly share code, notes, and snippets.

@helgasoft
Last active March 11, 2024 15:22
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save helgasoft/e9bcb87dfbfdaa6f52c673eb09d499fa to your computer and use it in GitHub Desktop.
Save helgasoft/e9bcb87dfbfdaa6f52c673eb09d499fa to your computer and use it in GitHub Desktop.
Demo Shiny: Leaflet JS plugin - layer control for grouping overlays
#' Demo - using Leaflet JS plugins in R and Shiny
#' directions from https://gist.github.com/jcheng5/c084a59717f18e947a17955007dc5f92
#' implementing groupings to overlay layers :
#' https://github.com/ismyrnow/leaflet-groupedlayercontrol
#' todo: would be nice to addMarkers to group layers from R, not only from JS
library(shiny)
library(leaflet)
library(htmlwidgets)
runApp( list(
ui = fluidPage( leafletOutput("mymap") ),
server = function(input, output, session) {
# workaround for the src/href problem - dnld/save locally ONCE
urlf <- 'https://raw.githubusercontent.com/ismyrnow/leaflet-groupedlayercontrol/gh-pages/dist/%s'
download.file(sprintf(urlf,'leaflet.groupedlayercontrol.min.js'), 'C:/Temp/L.Control.groupedlayer.js', mode="wb")
download.file(sprintf(urlf,'leaflet.groupedlayercontrol.min.css'), 'C:/Temp/L.Control.groupedlayer.css', mode="wb")
ctrlGrouped <- htmltools::htmlDependency(
name = 'ctrlGrouped',
version = "1.0.0",
# works in R and Shiny - download js/css files, then use this:
src = c(file = normalizePath('C:/Temp')),
script = "L.Control.groupedlayer.js",
stylesheet = "L.Control.groupedlayer.css"
)
registerPlugin <- function(map, plugin) {
map$dependencies <- c(map$dependencies, list(plugin))
map
}
output$mymap <- renderLeaflet({
map <- leaflet() %>%
setView(-104.99, 39.73, zoom = 10)
map <- map %>% registerPlugin(ctrlGrouped) %>%
onRender("function(el, x) {
var basemaps = {
Grayscale: L.tileLayer('http://{s}.tiles.wmflabs.org/bw-mapnik/{z}/{x}/{y}.png', {
maxZoom: 18,
attribution: '&copy; <a href=http://www.openstreetmap.org/copyright>OpenStreetMap</a>'
}),
Streets: L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 19,
attribution: '&copy; <a href=http://www.openstreetmap.org/copyright>OpenStreetMap</a>'
})
};
basemaps.Grayscale.addTo(this); // default base layer
var groups = {
cities: new L.LayerGroup(),
restaurants: new L.LayerGroup(),
dogs: new L.LayerGroup(),
cats: new L.LayerGroup()
};
L.marker([39.61, -105.02]).bindPopup('Littleton, CO.').addTo(groups.cities);
L.marker([39.74, -104.99]).bindPopup('Denver, CO.').addTo(groups.cities);
L.marker([39.73, -104.8 ]).bindPopup('Aurora, CO.').addTo(groups.cities);
L.marker([39.77, -105.23]).bindPopup('Golden, CO.').addTo(groups.cities);
L.marker([39.69, -104.85]).bindPopup('A restaurant').addTo(groups.restaurants);
L.marker([39.69, -105.12]).bindPopup('B restaurant').addTo(groups.restaurants);
L.marker([39.79, -104.95]).bindPopup('A dog').addTo(groups.dogs);
L.marker([39.79, -105.22]).bindPopup('B dog').addTo(groups.dogs);
L.marker([39.59, -104.75]).bindPopup('A cat').addTo(groups.cats);
L.marker([39.59, -105.02]).bindPopup('B cat').addTo(groups.cats);
// Overlay layers are grouped
var groupedOverlays = {
'Landmarks': {
'Cities': groups.cities,
'Restaurants': groups.restaurants
},
'Random': {
'Dogs': groups.dogs,
'Cats': groups.cats
}
};
var options = {
exclusiveGroups: ['Landmarks'], // use radio inputs
groupCheckboxes: true
};
L.control.groupedLayers(basemaps, groupedOverlays, options).addTo(this);
}")
})
}
))
@michaelgaunt404
Copy link

Hey! This is great, i've been trying to find a solution to this problem as well.

Do you know how you would do something like this with a map that is already constructed with mapview?

I would like to make the resulting map's legend say:

Places
|-> names
|-> village
Other
|-> Changed Name

install.packages("mapview")
install.packages("dplyr")
install.packages("magrittr")
library(mapview)
library(dplyr)
library(magrittr)

names = breweries %>%
select(brewery)

village = breweries %>%
select(village)

Complicated Name_layer = breweries %>%
select(number.of.types)

mapview(names, legend = F) +
mapview(village, legend = F) +
mapview(Complicated Name_layer, legend = F)

image

@tsalter
Copy link

tsalter commented Mar 10, 2024

Any chance you have figured out how to addMarkers to group layers from R, not only from JS?

@helgasoft
Copy link
Author

how to addMarkers to group layers

To group layers - yes:

leaflet() %>% 
setView(-104.99, 39.73, zoom = 10) %>%
addProviderTiles(providers$CartoDB.Positron) %>%
addLayersControl(
   overlayGroups = c('cities','restaurants'),
   options = layersControlOptions(collapsed = FALSE)) %>% 
hideGroup('restaurants') %>%  
addMarkers(lat=39.77, lng=-105.23, popup='Golden, CO.', group='cities') %>%
addMarkers(lat=39.69, lng=-104.85, popup='A restaurant', group='restaurants')

but to groupedOverlays - no.

@tsalter
Copy link

tsalter commented Mar 11, 2024

Thank you!
I was thinking to groupedOverlays - Way beyond my skills.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment