TheNerdyCat
TheNerdyCat

Reputation: 95

Shiny leaflet map tiles not appearing

Example data:

tab1_data <- data.table( id = c(1,2,3,4),
                         londd = c(-1.610245, -0.242566, -0.136315, -0.730095),
                         latdd = c(52.98752, 54.04599, 50.79249, 51.16059),
                         type = c("A", "B", "C", "D"),
                         price = c(175000, 61000, 62500, 72500))

I have followed the example set out in this SO post (much obliged, thank you). And I tried changing the map provider to MapBox as per what I saw in this link but upon output, the map does not render. Please see image below, the code is also below that.

Map Screenshot

Code:

library(leaflet)
library(data.table)

#Set up ui
ui <- fluidPage(
    titlePanel("Panel"),
    sidebarPanel(h5("", width=1),
                 checkboxGroupInput(inputId = "TypeFlag",label = h4("Type"), 
                                    choices = setNames(object = c("A", "B", "C", "D"),
                                                       nm = c("A", "B", "C", "D")),
                                    selected = c("A", "B", "C", "D")
                 ),
                 position="left"),
    
    #App mainPanel content and styles
    mainPanel(fluidRow(leafletOutput(outputId = "map")))
  )

#Set up server
server <- function(input, output){
  #Build leaflet map
  map <- leaflet(data = tab1_data) %>%
    addProviderTiles("MapBox", 
                     options = providerTileOptions(id = "mapbox.light", noWrap = FALSE, 
                                                   accessToken = Sys.getenv('MAPBOX_ACCESS_TOKEN'))) %>%
    fitBounds(~min(londd), ~min(latdd), ~max(londd), ~max(latdd))

  #Filter data
  datFilt <- reactive({
    MatSearch <- paste0(c('xxx', input$TypeFlag), collapse = "|")
    tab1_data[grepl(MatSearch,type)]
  })

  #Add markers based on selected flags
  observe({
    if(nrow(datFilt()) == 0) {
      print("Nothing selected")
      leafletProxy("map") %>%
        clearMarkerClusters()
    } else { #print(paste0("Selected: ", unique(input$InFlags&input$InFlags2)))
      print("Something Selected")
      leafletProxy("map", data=datFilt()) %>% 
        clearMarkerClusters() %>% 
        addCircleMarkers(lng = ~londd, lat = ~latdd,
                         clusterOptions = markerClusterOptions(), weight=3,
                         color = "#90EE90", opacity=1, fillColor = "#228B22", 
                         fillOpacity = 0.8)
    }
  })

  output$map <- renderLeaflet(map)
}

#Run app
shinyApp(ui = ui, server = server)

It is worth noting that if I replace the code inside addProviderTiles() with the below, it DOES work (but I prefer the aesthetic of MapBox and hope that I can use it!):

"Stamen.TonerLite", options = providerTileOptions(noWrap = TRUE)

I expect it has something to do with registering to MapBox? However I have had a functioning map without registering using this SO post as an example.

I have tried setting the map parameters a per the link at the beginning of the post, but this didn't work (it was worth a try). I get the same result if I open in browser as I do in the popup. Lastly, the checkboxes are functional and reactive.

Upvotes: 4

Views: 2614

Answers (2)

Matt Summersgill
Matt Summersgill

Reputation: 4242

While there could be some shiny related issues at play here (more on that later), It seems that the question could be reduced to the following:

library(leaflet)

## Works
leaflet() %>%
  addProviderTiles("Stamen.TonerLite") 

## Doesn't Work
leaflet() %>%
  addProviderTiles("MapBox", 
                   options = providerTileOptions(id = "mapbox.light",
                                                 noWrap = FALSE, 
                                                 accessToken = Sys.getenv('MAPBOX_ACCESS_TOKEN'))) 

If the second one using Mapbox still doesn't work for you, your accessToken is either invalid, expired, or not being stored/returned as an environment variable the way you expect.

To eliminate the question of if you have a valid token, try temporarily hard-coding it in place of the environment variable call.

Note: I found an actual working token to test on a blog post, the following snippet contains a partially redacted version.

library(leaflet)

MBaccessToken <- "pk.eyJxIjxxxWJyZxNraGxiLxxxIjQoxxxxHX1xpRSx9.9xPQxA3xdxyxAxPkxYxYE"

leaflet() %>%
  addProviderTiles("MapBox", 
                   options = providerTileOptions(id = "mapbox.light",
                                                 noWrap = FALSE, 
                                                 accessToken = MBaccessToken)) 

displays this:

map

If (and only if) that works, then move on to the following.

Part 2: Potential shiny issues

If you can get the map to render properly when running in an interactive session (I'm assuming RStudio) but the map will not render as a shiny application, the troubleshooting possibilities open up.

  • Is the application running exclusively in an interactive RStudio session, on a locally managed shiny-server, shinyapps.io, or another 3rd party cloud service?
  • When the application is running in that environment, what user is the app running as? How are that user's environment variables defined, and do you have control over them?

Long story short, if the application isn't deployed on the same server you're testing on and running as the same user, then the Sys.getenv() call will give a different result when deployed than you get when testing in RStudio.

A simple way to test this would be to add the following lines to your example app for testing purposes to make sure that the token is being read from the environment variable as expected.

Add somewhere in ui:

textOutput("token")

Add to server:

output$token <- renderText(Sys.getenv('MAPBOX_ACCESS_TOKEN'))

Upvotes: 1

MLavoie
MLavoie

Reputation: 9836

Your application is working fine. I tried two different mapbox tokens and they are both working. Try this:

accessToken = 'your_token_from_your_mapbox_account')) %>%

Upvotes: 1

Related Questions