r - R 传单 - 在已打开弹出窗口的地图上添加新标记
问题描述
我有一个显示传单地图的闪亮应用程序。该应用程序的一项功能允许用户在地图上添加新的地理标记。但是,我想让此类标记的弹出窗口在添加到地图后立即打开,但始终保持使用“x”按钮或单击地图将其关闭的可能性。
我已经阅读了传单文档的“标记”指南(“从图层继承的弹出方法”小节,非常详细的指南显然在 R 语言中不可用)并且我找到了这个选项openPopup()
。不幸的是,这似乎不适用于我的代码。这是一个简单的例子:
library(leaflet)
leaflet() %>%
addTiles() %>%
addMarkers(lng = -100,
lat = 50,
popup = "ALE",
options = popupOptions(openPopup = TRUE))
预期的行为是这个使用传单的在线工具中显示的行为。请尝试搜索地址并查看新标记是否立即打开了自己的弹出窗口。
在此先感谢您的帮助!
解决方案
代码
我想需要一点 JavaScript,因为界面似乎不支持此功能。
下面是一个闪亮的例子:
library(shiny)
library(leaflet)
library(shinyjs)
js_save_map_instance <- HTML(
paste(
"var mapsPlaceholder = [];",
"L.Map.addInitHook(function () {",
" mapsPlaceholder.push(this); // Use whatever global scope variable you like.",
"});", sep = "\n"
)
)
js_open_popup <- HTML(
paste("function open_popup(id) {",
" console.log('open popup for ' + id);",
" mapsPlaceholder[0].eachLayer(function(l) {",
" if (l.options && l.options.layerId == id) {",
" l.openPopup();",
" }",
" });",
"}", sep = "\n"
)
)
ui <- fluidPage(
tags$head(
tags$script(type = "text/javascript",
js_save_map_instance,
js_open_popup),
useShinyjs()
),
wellPanel(
fluidRow(
sliderInput("lng", "Longitude:", 10, 60, 35, 0.01),
sliderInput("lat", "Latitude:", 35, 75, 42.5, 0.01),
actionButton("add", "Add Marker")
)
),
fluidRow(
leafletOutput("map")
)
)
server <- function(input, output, session) {
map <- leaflet() %>%
addTiles() %>%
fitBounds(10, 35, 60, 75)
output$map <- renderLeaflet(
map
)
observeEvent(input$add, {
id <- paste0("marker", input$add)
leafletProxy("map") %>%
addMarkers(input$lng, input$lat, id,
"mymarkers",
popup = sprintf("%.2f / %.2f: %s", input$lng, input$lat,
id))
runjs(sprintf("setTimeout(() => open_popup('%s'), 10)", id))
})
}
shinyApp(ui, server)
评论
leaflet.js
不提供开箱即用的功能来在初始化后检索地图实例。因此,我们必须使用一种解决方法在初始化时显式保存地图。这是在存储在 .js 中的 JS 代码中完成的js_save_map_instance
。这个想法取自Find Leaflet map object after initialisation。- 我们创建一个 JS 函数,它获取我们要为其打开弹出窗口的标记的 id。在这个函数中,我们获取数组的第一个元素,其中存储了所有地图实例(如果页面上应该有多个传单地图,则需要进行调整。
- 在这个地图实例上,我们可以遍历所有层,如果
layerId
等于我们正在寻找的那个,我们可以调用openPopup
这个层。(注意理想情况下,我们可以直接访问该层(同样我在 API 中没有找到任何函数)并且我们可以使用私有_layer
属性,但由于它是私有的,所以我使用循环方法。) - 剩下的,就是
open_popup
在shiny
旁边正确的地方打电话。我需要添加一个小的延迟以避免我们在添加标记之前调用该函数。
结果
推荐阅读
- python - 如何在 Django 模型中将用户用作 ForeignKey
- c++ - 在功能块中使用新运算符时住在堆或堆栈上?
- node.js - 在 NodeJS + Typescript AWS Lambda 上进行单元测试
- python - 有没有办法递归地找到一组数字可以加起来为某个数字的不同方式?
- amazon-neptune - 无法在海王星工作台中使用 python 添加顶点
- fancybox - 使用新类型在按钮单击时更新 fancybox 当前幻灯片内容
- python - Python 三引号和百分比 (%) 语法
- javascript - 在第一次和第二次出现正斜杠之间替换字符串
- javascript - 动画 javascript div 上的文本
- reactjs - ReactJS material-ui 'TypeError: onSelect is not a function' tabHandler