是否可以在 Shiny 环境中将 Leaflet 控件移到地图 div 之外?
来自以下代码:
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
我看到了这个问题,但它是特定于leaflet.js的,它与Shiny有很大不同。有什么办法可以做到这一点吗?
用 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)