【问题标题】:R leaflet - Add a new marker on the map with the popup already openedR 传单 - 在已打开弹出窗口的地图上添加新标记
【发布时间】:2021-05-20 06:46:47
【问题描述】:

我有一个显示传单地图的闪亮应用。该应用程序的一项功能允许用户在地图上添加新的地理标记。但是,我想让此类标记的弹出窗口在添加到地图后立即打开,但始终保留使用“x”按钮或单击地图。

我已经阅读了leaflet documentation 的“标记”指南(“从图层继承的弹出方法”小节,非常详细的指南显然在 R 语言中不可用)并且我发现了这个选项openPopup()。不幸的是,这似乎不适用于我的代码。这是一个简单的例子:

library(leaflet)

leaflet() %>% 
  addTiles() %>% 
  addMarkers(lng = -100,
             lat = 50,
             popup = "ALE",
             options = popupOptions(openPopup = TRUE))

预期的行为是使用传单的online tool 中显示的行为。请尝试搜索地址并查看新标记是否立即打开了自己的弹出窗口。

提前感谢您的帮助!

【问题讨论】:

    标签: r shiny leaflet popup marker


    【解决方案1】:

    代码

    我想需要一点 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_save_map_instance 中存储的 JS 代码中完成的。这个想法来自Find Leaflet map object after initialisation
    • 我们创建一个 JS 函数,它获取我们要为其打开弹出窗口的标记的 id。在此函数中,我们获取数组的第一个元素,其中存储了所有地图实例(如果页面上应该有多个传单地图,则需要进行调整。
    • 在这个地图实例上,我们可以遍历所有层,如果layerId 等于我们正在寻找的那个,我们可以在这个层上调用openPopup。 (NB 理想情况下,我们可以直接访问该层(同样,我在 API 中没有找到任何函数)并且我们可以使用 private _layer 属性,但是因为它是私有的,我使用循环方法。)
    • 剩下的就是在shiny 一侧的正确位置调用open_popup。我需要添加一点延迟以避免我们在添加标记之前调用该函数。

    结果

    【讨论】:

    • 我确认这是闪亮和 R 环境的正确答案。非常感谢您的完美解释!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-03
    • 1970-01-01
    相关资源
    最近更新 更多