Search code examples
rshinyr-leaflet

Publishing a shiny/leaflet map made in R to a website


I'm helping a friend doing some research on the number of breweries in CT. With help from this community I was able to make a map of breweries in leaflet and was able to add a slider using shiny. Now I want to be able to give my friend the map so he can add it to the website where he is publishing his research. I'm new to some of this and was wondering if anybody had some ideas for me. Here is the code (thanks to Ben) I used to make the map:

library(shiny)
library(leaflet)

ui <- bootstrapPage(
  tags$style(type = "text/css", "html, body {width:100%;height:100%}"),
  leafletOutput("map", width = "100%", height = "100%"),
  absolutePanel(bottom = 30, right = 10,
                textOutput("Counter"),
                sliderInput("Year", "Year", 1990, 2000, value = 1995, step = 1, sep = "")
  )
)

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

  sliderData <- reactive({
    breweries_subset %>%
      filter(YearOpened <= input$Year)
  })

  output$Counter <- renderText(
    paste("Number Breweries: ", nrow(sliderData()))
  )

  output$map <- renderLeaflet({
    leaflet() %>%
      addTiles() %>%
      fitBounds(min(breweries_subset$Longitude), min(breweries_subset$Latitude),
                max(breweries_subset$Longitude), max(breweries_subset$Latitude))
  })

  observe({
    leafletProxy("map", data = sliderData()) %>%
        clearMarkers() %>%
        addProviderTiles(provider = 'Esri.WorldStreetMap') %>%
        addAwesomeMarkers(icon = beer_icon,
                          group = 'Breweries',
                          popup = ~ Name)
  })
}

shinyApp(ui = ui, server = server)

UPDATE

I took your suggestions and tried publishing to shinyapps.io. Here's the code I used:

For ui.R:

library(shiny)
library(leaflet)

ui <- bootstrapPage(
    tags$style(type = "text/css", "html, body {width:100%;height:100%}"),
    leafletOutput("map", width = "100%", height = "100%"),
    absolutePanel(bottom = 30, right = 10,
                  textOutput("Counter"),
                  sliderInput("Year", "Year", 1990, 2019, value = 1995, step = 1, sep = "")
    )
)

And for server.R:

library(shiny)
library(leaflet)
library(leaflet.extras)
library(fontawesome)
library(rsconnect)
function(input, output, session) {
    ct_breweries <- read.csv('ct_breweries.csv', header=TRUE, sep=',')
    sliderData <- reactive({
        ct_breweries %>%
            filter(YearOpened <= input$Year)
    })
    output$Counter <- renderText(
        paste('Number of Breweries: ', nrow(sliderData()))
    )
    output$map <- renderLeaflet({
        leaflet() %>%
            addTiles() %>%
            fitBounds(min(ct_breweries$Longitude), min(ct_breweries$Latitude),
                      max(ct_breweries$Longitude), max(ct_breweries$Latitude))
    })
    observe({
        leafletProxy('map', data = sliderData()) %>%
            clearMarkers() %>%
            addProviderTiles(provider = 'Esri.WorldStreetMap') %>%
            addAwesomeMarkers(icon = beer_icon,
                              group = 'Breweries',
                              popup = ~ Name)
    })
}

It works fine locally. When I try to publish it, I get a Disconnected from Server error. In the logs it says something about 'YearOpened' not found. There's definitely a column for that in the .csv. I'm wondering if it has something to do with the call to the fall. Do you have any ideas?


Solution

  • Try adding all the package loading and dataset reading to a global.R file (in the same app folder) as below:

    library(shiny)
    library(leaflet)
    library(leaflet.extras)
    library(fontawesome)
    library(rsconnect)
    
    ct_breweries <- read.csv('ct_breweries.csv', header=TRUE, sep=',')
    

    You can then remove these from ui.R and server.R.

    The problem seems to be that the dataset is not visible to the server - this should fix that. Also, make sure that the csv file is in the same folder.

    Update

    Based on my comment above, if this is sufficient, you can just save an html file of the map that you can send to your friend to open in a browser. I have attempted to write the code without your data so this may not work.

    library(leaflet)
    library(fontawesome)
    library(htmlwidgets)
    
    ct_breweries <- read.csv('ct_breweries.csv', header=TRUE, sep=',')
    
    leaflet_map <- leaflet(data = ct_breweries) %>%
        addProviderTiles(provider = 'Esri.WorldStreetMap') %>%
        addAwesomeMarkers(icon = beer_icon,
                          group = ~ YearOpened,
                          popup = ~ Name) %>%
        addLayersControl(
            overlayGroups = 1990:2000,
            options = layersControlOptions(collapsed = FALSE)
        ) %>% hideGroup(~ YearOpened)
    
    saveWidget(leaflet_map, file="leaflet_map.html")
    

    It does lose the slider option - replaced with checkboxes. You can remove the hideGroup() and collapsed = FALSE to see other options. This might be easier assuming the slider is not a requirement.

    This file is saved offline but you will need an internet connection to fetch the leaflet map tiles.