Leaflet with Shiny: reacting to input$map_zoom with leafletProxy()

1,893 views
Skip to first unread message

Andrew Caines

unread,
Mar 15, 2016, 4:29:37 AM3/15/16
to Shiny - Web Framework for R
Hello,

I have a Shiny map app using Leaflet (great package: thank you!)
I'd like my circles to increase in size as the user zooms in on the map. I have a reactive function for input$map_zoom, and use leafletProxy() to say that the circle radius should equal the zoom level. However circle radius does not change at all. Please can anyone help correct what I'm doing / identify a bug?

Reproducible example below, using an amended version of a leaflet demo from http://rstudio.github.io/leaflet/shiny.html
I've marked my amendments with a comment starting "# AC:…"

thanks in advance,
Andrew

library(shiny)

library(leaflet)

library(RColorBrewer)


ui <- bootstrapPage(

 tags$style(type = "text/css", "html, body {width:100%;height:100%}"),

 leafletOutput("map", width = "100%", height = "100%"),

 absolutePanel(top = 10, right = 10,

   sliderInput("range", "Magnitudes", min(quakes$mag), max(quakes$mag),

     value = range(quakes$mag), step = 0.1

   ),

   selectInput("colors", "Color Scheme",

     rownames(subset(brewer.pal.info, category %in% c("seq", "div")))

   ),

   checkboxInput("legend", "Show legend", TRUE)

 )

)


server <- function(input, output, session) {

 # Reactive expression for the data subsetted to what the user selected

 filteredData <- reactive({

   quakes[quakes$mag >= input$range[1] & quakes$mag <= input$range[2],]

 })

 # This reactive expression represents the palette function,

 # which changes as the user makes selections in UI.

 colorpal <- reactive({

   colorNumeric(input$colors, quakes$mag)

 })


 output$map <- renderLeaflet({

   # Use leaflet() here, and only include aspects of the map that

   # won't need to change dynamically (at least, not unless the

   # entire map is being torn down and recreated).

   leaflet(quakes) %>% addTiles() %>%

     fitBounds(~min(long), ~min(lat), ~max(long), ~max(lat))

 })


 ## AC: collects map zoom value

 mapzoom <- reactive({

   input$map_zoom

 })


  # Incremental changes to the map (in this case, replacing the

 # circles when a new color is chosen) should be performed in

 # an observer. Each independent set of things that can change

 # should be managed in its own observer.

 observe({

   pal <- colorpal()
   
## AC: circle radius set to equal map zoom

   circleRadius <- mapzoom()

   leafletProxy("map", data = filteredData()) %>%

     clearShapes() %>%
     
## AC: radius = circle radius

      addCircles(radius = circleRadius, weight = 1, color = "#777777",

       fillColor = ~pal(mag), fillOpacity = 0.7, popup = ~paste(mag)

     )

 })

 

 # Use a separate observer to recreate the legend as needed.

 observe({

   proxy <- leafletProxy("map", data = quakes)

   # Remove any existing legend, and only if the legend is

   # enabled, create a new one.

   proxy %>% clearControls()

   if (input$legend) {

     pal <- colorpal()

     proxy %>% addLegend(position = "bottomright",

       pal = pal, values = ~mag

     )

   }

 })

}


shinyApp(ui, server)




hol...@geocf.com

unread,
Mar 15, 2016, 6:15:08 PM3/15/16
to Shiny - Web Framework for R
Are you sure you don't need addCircleMarkers? They stay the same size and 10 looked good. This way you aren't passing all the points back to the client on each zoom. If you need addCircles, this sorta works (although some appear to have the wrong size at mid-zoom levels... very odd):

  observe({
    pal <- colorpal()
    req(mapzoom())
    req(filteredData())
    circleRadius <- as.numeric(mapzoom())*100
    filteredData <- filteredData()
    leafletProxy("map") %>%
      clearShapes() %>% 
      addCircles(lng = filteredData$long, lat = filteredData$lat, radius = circleRadius, 
                 weight = 1, color = "#777777", fillColor = pal(filteredData$mag), 
                 fillOpacity = 0.7, popup = as.character(filteredData$mag)
      )
  })

Andrew Caines

unread,
Mar 15, 2016, 7:17:11 PM3/15/16
to Shiny - Web Framework for R
I am indeed using circle markers in my 'real' problem, which works fine now, thank you!
But weirdly, the circles still don't resize even with the code you posted .. but anyway, the circle markers are what I need to use, so that's all fine.
Reply all
Reply to author
Forward
0 new messages