Search code examples
rshinyr-leaflet

How do I return the position of a Leaflet map in shiny once it's been moved by the user?


The background to the question is as follows:

I have a shiny app that presents data on a leaflet map. That data can be filtered and presented in different ways. However, when the user zooms in and/or moves the map, and THEN filters the data, the map will revert back to the initial map view:

output$mymap <- renderLeaflet({
 leaflet() %>%
      setView(lng = 0, lat = 30, zoom = 4)  %>% #setting the view over ~ center of North America
      addTiles(options = providerTileOptions(noWrap = TRUE)) 
})

What I am looking for is some way of returning the position of the map such that when the data is updated in a proxy leaflet function I can set the view as well. The following is what I'm trying to achieve (I've made up a move equivalent of input$mymap_click).

observeEvent(input$mymap_move, {

move <- input$mymap_move
mlat <- move$lat
mlon <- move$lon
mzoom <- move$zoom

leafletProxy('mymap') %>% 
      setView(lng = mlng, lat = mlat, zoom = mzoom) %>%
      addMarkers(data = data.join,
                 lat = data.join$a.lat,
                 lng = data.join$a.lon,
                 icon = icon.func[data.join$SYMBOL_CODE],
                 popup = data.join$ANCHOR)

})

Solution

  • Once your map is initialised, you can access the current state of your map via input$mymap_center and input$mymap_zoom (and if you wish you can access input$mymap_bounds)

    There are just 2 things you need to pay attention to:

    • You have to check whether initialisation is complete yet, and if not give manual parameters (or Shiny won't know what starting position to use)
    • Unless you isolate the lookup, your map will re-render every time you change the view, which is probably not what you want (it makes your app really slow, and unworkable to the user)

    So putting it all together, I think this code should do what you wish:

    output$mymap <- renderLeaflet({
      isolate({
        if ("mymap_center" %in% names(input)) {
          mapparams <- list(center = input$mymap_center,
                            zoom = input$mymap_zoom)
        } else {
          mapparams <- list(center = list(lng=0, lat=30),
                          zoom = 4) #setting the view over ~ center of North America
        }
      })
      leaflet() %>%
          setView(lng = mapparams$center$lng, lat = mapparams$center$lat, zoom = mapparams$zoom)  %>% 
          addTiles(options = providerTileOptions(noWrap = TRUE)) 
    })