rstudio / leaflet

R Interface to Leaflet Maps
http://rstudio.github.io/leaflet/
Other
805 stars 509 forks source link

How to refresh/reset map? #755

Open Camil88 opened 2 years ago

Camil88 commented 2 years ago

Hi, in some particular case when I change tabs in my app the leaflet map disappears (to be more precise - instead of the map I see just gray canvas). I just wanted to somehow refresh/reset map programatically and get it back to initial state but don't think I can do it with this leaflet-for-shiny library. I just googled it and found some raw JS which could help to solve the problem. Unfortunately it doesn't work here. I tried setting view, remove map, fit bounds etc. but in vain. Below you can find my tries (let's say my leaflet map created in shiny is called myMap):

      var map = L.map('myMap');  
      if(map != 'undefined' || map != null) {
        map.remove(); 
      } 
      var map = L.map('myMap');
      map.off();
      map.remove();
      map.setView([51.505, -0.09], 13);
      var map = L.map('myMap');
      var container = L.DomUtil.get('myMap'); //here I first check if map is loaded to DOM
         if(container != null){
            container._leaflet_id = null;
         }
      map.invalidateSize();  
      var map = L.map('myMap');
      var bounds = L.latLng(40.737, -73.923).toBounds();
      map.fitBounds(bounds, {animation: false});

I also tried to use it along with onRender function but in vain:

    leaflet() %>%
    ..... %>%
    htmlwidgets::onRender("
    function() {
      var myMap = this;
      myMap.invalidateSize();
    }")

None of them works for me, I always get the same error in console: Map container is already initialized And even if I try to hit this simple code to console: var map = L.map('myMap'); I got the same error in return. Seems like I can't reach to myMap leaflet object. How can I solve this issue?

trafficonese commented 3 weeks ago

Maybe the following works.

You need the package shinyjs, initialize it with useShinyjs() in your UI, then you can get the leaflet map using this: $("#map").data("leafletMap") (map is my output ID for the map) and then you should be able to trigger this: $("#map").data("leafletMap").invalidateSize();

Full Shiny example:

library(shiny)  
library(shinyjs)  
library(leaflet)

ui <- navbarPage("Refresh Map",
                 useShinyjs(),
                 tabPanel("Map",
                          actionButton("reset", "Reset"),
                          leafletOutput("map")
                          ),
                 tabPanel("Summary")
)

server <- function(input, output, session) {
  observeEvent(input$reset, {
    runjs('$("#map").data("leafletMap").invalidateSize();')
  })
  output$map <- renderLeaflet({
    leaflet()  %>% 
      addTiles()
  })
}
shinyApp(ui, server)