在Shiny环境中将Leaflet控件放在map div之外

时间:2017-03-07 21:00:04

标签: javascript html r shiny leaflet

是否可以在Shiny环境中将Leaflet控件移到map div之外?

实施例: enter image description here

从以下代码:

library(shiny)
library(leaflet)

shinyApp(

  ui <- fluidPage(
    sidebarPanel("This is where I want to put the leaflet layers control", width = 3), 
    mainPanel(
      leafletOutput("map", width = "100%"), 
      width = 9)
  ), 

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

    output$map <- renderLeaflet({
      leaflet() %>% 
        addProviderTiles("Esri.WorldTerrain", group = "Layer1") %>% 
        addProviderTiles("Esri.WorldImagery", group = "Layer2") %>% 
        addLayersControl(position = "topleft", 
                         baseGroups = c("Layer1", "Layer2"), 
                         options = layersControlOptions(collapsed = F))
    })  # END RENDERLEAFET
  }  # END SERVER
)  # END SHINYAPP

我看到this question,但它特定于leaflet.js,与Shiny明显不同。有没有办法做到这一点?

1 个答案:

答案 0 :(得分:2)

JS可以(部分?)。

在Shiny中使用JS

在闪亮的library(shinyjs)中使用JS是一个很好的捷径。在ui端使用useShinyjs(),在服务器端使用runjs()

修改HTML

当您想要修改DOM时,您必须知道必须等到DOM完全构建,然后才能修改它。使用session$onFlushed(function() {}确保仅在DOM完全构建时才开始修改。

重新定位HTML元素

首先,您必须知道要重新定位的元素和要插入的目标的命名方式。为此,运行应用程序(在浏览器中)右键单击所需元素并选择“检查”。 接下来,程序将保存变量中的“元素到重新定位”,将其从叶子图中删除并将其添加到地图之外。

JS代码可能如下所示:

     var targetName = "div.leaflet-control-layers.leaflet-control-layers-expanded.leaflet-control"
     var target = document.querySelector(targetName);
     var dest = document.querySelector("div.col-sm-3");
     document.querySelector(targetName).remove()
     dest.appendChild(target)

<强>挑战 如果你把它们放在一起就会注意到,控件不在灰色框内,而是在它下面。鉴于上面的代码,原因是它被附加到div.col-sm-3而不是form.well(因为它不适用于form.well)。我有想法在UI tags$div(id = "insertContainer", "")中添加一个空容器并将其插入其中,但这也无效。我不知道你进入灰色框内有多重要,看起来可能更好。也许有人可以帮忙。

<强>代码

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

  ui <- fluidPage(
    useShinyjs(),
    sidebarPanel(HTML("This is where I want to put the leaflet layers control"), width = 3, height = 5), 
    mainPanel(
      leafletOutput("map", width = "100%"), 
      width = 9)
  )

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

    session$onFlushed(function() {
      runjs('
             var targetName = "div.leaflet-control-layers.leaflet-control-layers-expanded.leaflet-control"
             var target = document.querySelector(targetName);
             var dest = document.querySelector("div.col-sm-3");
             document.querySelector(targetName).remove()
             dest.appendChild(target)
      ')
    })

    output$map <- renderLeaflet({
      leaflet() %>% 
        addProviderTiles("Esri.WorldTerrain", group = "Layer1") %>% 
        addProviderTiles("Esri.WorldImagery", group = "Layer2") %>% 
        addLayersControl(position = "topleft", 
                         baseGroups = c("Layer1", "Layer2"), 
                         options = layersControlOptions(collapsed = F))
    })  # END RENDERLEAFET
  }  # END SERVER


runApp(shinyApp(ui, server), launch.browser = TRUE)