leaflet-shiny: changing initalTileLayer

961 views
Skip to first unread message

Chris Holcomb

unread,
Aug 3, 2014, 11:48:02 PM8/3/14
to shiny-...@googlegroups.com
Hi,

First of all this is a great package, it's easy to grab the map bounds and zoom level, among other features. However, I am having difficulty dynamically changing the initialTileLayer using shiny-leaflet.

I have created a minimal example using two different initialTileLayer's. It seems to require two corresponding maps in server.R. Here is the ui.R:

library(shiny);library(leaflet)
shinyServer(function(input, output, session) {
  output$map1 <- reactive(TRUE)
  map1 <- createLeafletMap(session, "map1")
  output$map2 <- reactive(TRUE)
  map2 <- createLeafletMap(session, "map2")
}) 

It also requires a styles.css in the same directory as server.R and ui.R:

div.outer {
  position: fixed;
  top: 41px;
  left: 0;
  right: 0;
  bottom: 0;
  overflow: hidden;
  padding: 0;
}

Here's the ui.R:

library(shiny);library(leaflet)
shinyUI(navbarPage("Switch Map",
   tabPanel("Map",
      conditionalPanel(
        condition = "input.bmappick == 'MapQuestOpen.Aerial'",
        div(class="outer",tags$head(includeCSS("styles.css")),
        leafletMap("map1", "100%", "100%",
                 initialTileLayer = "http://oatile3.mqcdn.com/tiles/1.0.0/sat/{z}/{x}/{y}.jpg",
                 initialTileLayerAttribution = 
                    HTML('Tiles Courtesy of <a href="http://www.mapquest.com/">MapQuest</a> &mdash; 
                    Portions Courtesy NASA/JPL-Caltech and U.S. Depart. of Agriculture, Farm Service Agency'),
                 options=list(center = c(40, -98.85),zoom = 5)))),
      conditionalPanel(
        condition = "input.bmappick == 'OpenStreetMap'",
        div(class="outer",tags$head(includeCSS("styles.css")),
            leafletMap("map2", "100%", "100%",
                       initialTileLayer = "http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",
                       initialTileLayerAttribution = 
                         HTML('Tiles Courtesy of <a href="http://openstreetmap.org">OpenStreetMap</a> 
               contributors, <a href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>'),
                       options=list(center = c(40, -98.85),zoom = 5)))
      ),
      absolutePanel(top = 60, left = "auto", right = 20, bottom = "auto",
          selectInput("bmappick", "Background Map",c("OpenStreetMap" = 'OpenStreetMap',
         "MapQuestOpen.Aerial"= 'MapQuestOpen.Aerial'),selected = c("OpenStreetMap")))) ))

The background map that is not selected first by default through "bmappick" never fills the entire screen and appears to be a single tile. Is there a way to do this? I greatly appreciate any help.

I know leaflet has the ability to add a "layers control" to the map (http://leafletjs.com/examples/layers-control.html) but I don't see a reference to control.layers in the bindings (https://github.com/jcheng5/leaflet-shiny/blob/4cf37eb81342925bb3537c1678546d50b82f54f7/inst/www/binding.js). I'm new to Javascript so I could be totally missing something, and I don't need to use Leaflet directly for this.

Regards,

Chris


P.S. to install leaflet-shiny:

if (!require(devtools))
  install.packages('devtools')
devtools::install_github('leaflet-shiny', 'jcheng5')


Chris Holcomb

unread,
Aug 5, 2014, 8:44:09 PM8/5/14
to shiny-...@googlegroups.com
My workaround in case somebody else runs into this. 

ui.R:

library(shiny);library(leaflet)
shinyUI(navbarPage("Switch Map",
   tabPanel("Map",
      div(class="outer",tags$head(includeCSS("styles.css")),
          htmlOutput("mapp",inline=TRUE)),
      absolutePanel(top = 60, left = "auto", right = 20, bottom = "auto",
          selectInput("mapPick", "Background Map",c("OpenStreetMap" = "http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",
         "MapQuestOpen.Aerial"= "http://oatile3.mqcdn.com/tiles/1.0.0/sat/{z}/{x}/{y}.jpg"),

server.R:

library(shiny);library(leaflet)
shinyServer(function(input, output, session) {
  output$map1 <- reactive(TRUE)
  map1 <- createLeafletMap(session, "map")
  output$mapp <- renderUI({
    input$mapPick
    isolate({
    leafletMap("map", "100%", "100%",
       initialTileLayer = input$mapPick,
       initialTileLayerAttribution = HTML('Fix This Later'),
       options=list(center = center(),zoom = zoom()))
    })
  })
  zoom <- reactive({
    ifelse(is.null(input$map_zoom),5,input$map_zoom)
  })
  center <- reactive({
    if(is.null(input$map_bounds)) {
      c(40, -98.85)
    } else {
      map_bounds <- input$map_bounds
      c((map_bounds$north + map_bounds$south)/2.0,(map_bounds$east + map_bounds$west)/2.0)
    }
  })
})

Michael Kalnoky

unread,
Dec 29, 2014, 9:02:30 PM12/29/14
to shiny-...@googlegroups.com
Dear Chris,

This solution worked wonderfully for my application, however now I am no longer seeing the markers that I add to the tile layers when I use this method.  Have you had any luck adding markers using  map$addCircle function?   Many thanks!

Sincerely,

Michael Kalnoky

Chris Holcomb

unread,
Jan 14, 2015, 9:15:05 PM1/14/15
to shiny-...@googlegroups.com

For some reason you need to delay the drawing of polygons/etc ala this example.

You may want to check out RStudio's new Shiny package. I'm still waiting on a couple features (notably WMS overlays) but they are making great progress and this may already work for your use case. To those interested here is an example of WMS getfeature requests with WMS leaflet plug-in. It looks like the new package has the same methods as the old one although the documentation indicates that they are still improving its integration with Shiny.

Chris
Reply all
Reply to author
Forward
0 new messages