18

In leaflet, I would normally create a map with:

server.R

shinyServer(function(input, output, session) {
url <- "custommapboxurl"
attrib <- "Maps by http://www.mapbox.com/Mapbox"

...
     map_out <- reactive({

        map <- leaflet()%>%
        addTiles(urlTemplate = url, attribution = HTML(attrib))%>%
        addPolygons(data = sub_shape,
                    fill = TRUE,
                    fillColor = colors$color,
                    fillOpacity = .8,
                    stroke = TRUE,
                    weight = 3,
                    color = "white",
                    dashArray = c(5,5),
                    popup = pops
        )
    })

    output$myMap <- renderLeaflet({
            map_out()
    })
...
})

sub_shape above is my shapefile (in this case, zip codes in the US), and colors$color is a dynamic vector of colours that corresponds to each shape. You could recreate with the link here: http://www.nws.noaa.gov/geodata/catalog/national/html/province.htm, and colors <- data.frame(color = colorRampPalette(c("white","blue"))(13))

ui.R

shinyUI(
    ...
    leafletOutput('myMap', width = "100%" , height = "100%")
    ...
)

This gives:

enter image description here

What I would like to do is change the vector of colours based on a user's input. For example, they might select a different variable to colour each zip code by, generating a new gradient.

Shiny allows us to do this, as if I change the color vector based on an input widget, the reactive function refreshes, and recreates the map based on the new vector. The problem is that with large shapefile objects, this refresh takes a long time.

Is there any way to change the color of the currently rendered shapes directly, without recreating the entire layer? It seems like the color argument is locked within the leaflet() function. Is there any other way to get at it?

Chris
  • 6,302
  • 1
  • 27
  • 54
  • 4
    We just added full shiny support last week in leaflet (https://github.com/rstudio/leaflet), and you can either wait for detailed documentation (we are working on it), or install the current development version and check out the help page of the function `leafletProxy()`. – Yihui Xie May 07 '15 at 04:52
  • 6
    @Yihui thanks for your response, and for your work on this package. I have looked at leafletProxy, and it seems the motivation is right for what I want to do. However, my bottleneck above is the addPolygons step, which seems to be what I would `%>%` into the leafletProxy argument. Is there a way to pass a new colour palette to an already created addPolygons() layer? – Chris May 12 '15 at 13:32

1 Answers1

1

To illustrate @Yihui Xie's comment, here is an example using leafletProxy to change the colors of the Polygon, based on a selectInput.

library(shiny)
library(leaflet)
library(sp)
library(raster)

## Spatial Polygon ##########
Sr1 = Polygon(cbind(c(2,4,4,1,2),c(2,3,5,4,2)))
Sr2 = Polygon(cbind(c(5,4,2,5),c(2,3,2,2)))
Sr3 = Polygon(cbind(c(4,4,5,10,4),c(5,3,2,5,5)))
Sr4 = Polygon(cbind(c(5,6,6,5,5),c(4,4,3,3,4)), hole = TRUE)
Srs1 = Polygons(list(Sr1), "s1")
Srs2 = Polygons(list(Sr2), "s2")
Srs3 = Polygons(list(Sr3, Sr4), "s3/4")
SpP = SpatialPolygons(list(Srs1,Srs2,Srs3), 1:3)
SpPDF <- SpatialPolygonsDataFrame(SpP, data = data.frame(x=1:length(SpP)), match.ID = F)
Extent = extent(SpPDF)

## UI ##########
ui <- fluidPage(
  selectInput("col", label = "Select a color", choices = c("Blues", "viridis", "magma")),
  leafletOutput("map")
)

## SERVER ##########
server <- function(input, output) {
  output$map <- renderLeaflet({
    leaflet()  %>% 
      addTiles() %>% 
      fitBounds(lng1 = Extent[1],lat1 = Extent[3], lng2 = Extent[2], lat2 = Extent[4])
  })

  observe({
    req(input$col)
    pal = colorFactor(input$col, domain = factor(SpPDF$x))
    leafletProxy("map") %>%
      addPolygons(data = SpPDF, color = ~pal(factor(SpPDF$x)))
  })
}

shinyApp(ui, server)
SeGa
  • 9,454
  • 3
  • 31
  • 70
  • 2
    Thanks SeGa, this is a helpful example of how to implement the LeafletProxy code. I still think this has the issue of adding the polygons via proxy, instead of just updating the colours... – Chris Jun 26 '18 at 18:42
  • 2
    That is true, just the map doesn't have to be redrawn. But I dont know if its possible to just change the colors, as it sounds logical that the shapefile has to be recreated with different colors. – SeGa Jun 27 '18 at 07:31