简体   繁体   English

将Leaflet控件置于Shiny环境中的地图div之外

[英]Put Leaflet controls outside of map div in Shiny environment

Is it possible to move Leaflet controls outside of the map div in a Shiny environment? 在Shiny环境中是否可以将Leaflet控件移至map div之外?

Example: 例: 在此处输入图片说明

From the following code: 从以下代码:

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

I saw this question , but it was specific to leaflet.js, which differs significantly from Shiny. 我看到了这个问题 ,但它特定于leaflet.js,与Shiny明显不同。 Is there any way to do this? 有什么办法吗?

It is (partly?) possible with JS. JS有(部分吗?)可能。

Using JS within Shiny 在Shiny中使用JS

To use JS within shiny library(shinyjs) is a nice shortcut. 在闪亮的library(shinyjs)使用JS是一个不错的捷径。 Use useShinyjs() on the ui side and runjs() on the server side. 使用useShinyjs()在UI端和runjs()在服务器端。

Modify HTML 修改HTML

As you want to modify the DOM, you have to know that one has to wait until the DOM is completely build, before you can modify it. 当您要修改DOM时,必须知道必须等到DOM完全构建后才能进行修改。 Use session$onFlushed(function() {} to ensure you start modifying only when the DOM is completely build. 使用session$onFlushed(function() {}确保仅在完全构建DOM时才开始修改。

Repositioning the HTML elements 重新定位HTML元素

First, you will have to know how the elements, you want to reposition and the target where you want to insert it, are named. 首先,您将必须知道要重新定位的元素以及要在其中插入目标的目标的命名方式。 In order to do so run the app (in a browser) right click on the required element and choose "inspect". 为此,请在浏览器中运行该应用程序,然后在所需元素上单击鼠标右键,然后选择“检查”。 Next, the procedure would be to save the "element-to-reposition" in a variable, remove it from the leafletmap and add it outside the map. 接下来,过程将是将“要重定位的元素”保存在变量中,将其从传单地图中删除,然后将其添加到地图外部。

The JS code could look like this: 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)

Challenge If you put that all together you will notice, the control is not within the grey box, but below it. 挑战如果将所有内容放在一起,您会发现控件不在灰色框内,而是在灰色框下。 Given the code above, the reason is that it was appended to div.col-sm-3 and not to form.well (because it does not work for form.well ). 给定上面的代码,原因是它被附加到div.col-sm-3而不是form.well (因为它不适用于form.well )。 I had the idea to add an empty container in the UI tags$div(id = "insertContainer", "") and insert it in there, but that doesn´t work either. 我有个主意,要在UI tags$div(id = "insertContainer", "")添加一个空容器,然后将其插入其中,但这也不起作用。 I dont know how important it is for you to get in within the grey box, would look better probably. 我不知道进入灰色框对您有多重要,可能看起来会更好。 Maybe someone could help out there. 也许有人可以帮忙。

Code

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)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM