【问题标题】:Does markercluster work together with leafletProxy() and option iconCreateFunction?markercluster 是否与 LeafletProxy() 和选项 iconCreateFunction 一起使用?
【发布时间】:2018-06-04 00:17:38
【问题描述】:

我做错了什么,或者为什么下面的例子不起作用?我正在尝试使用选项iconCreateFunction 在 R Shiny 应用程序中使传单标记集群插件与leafletProxy() 一起使用。插件是否无法使用leafletProxy()向地图添加自定义图标标记?

当我按下第一个按钮并在下面的示例中缩小时,我收到一条错误消息:

TypeError: this._group.options.iconCreateFunction 不是函数

我尝试从 markercluster 文档中复制the original example

library(shiny)
library(dplyr)
library(leaflet)

ui <- fluidPage(
  titlePanel("Hello Shiny!"),
  sidebarLayout(
    sidebarPanel(
      actionButton(inputId = "my_button1",
                   label = "Use leafletProxy()"),
      actionButton(inputId = "my_button2",
                   label = "Use renderLeaflet()")
    ),
    mainPanel(
      leafletOutput(
        outputId = "map",
        width = "100%",
        height = "300px"
      )
    )
  )
)

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

  some_data <- data.frame(
    "lon"=c(4.905167,4.906357,4.905831),
    "lat"=c(52.37712,52.37783,52.37755),
    "number_var"=c(5,9,7),
    "name"=c("Jane","Harold","Mike"),
    stringsAsFactors = F
  )

  output$map <- renderLeaflet({
    return(
      leaflet(data = some_data[0,]) %>%
         addProviderTiles(providers$CartoDB.Positron) %>%
        fitBounds(
          min(some_data$lon),
          min(some_data$lat),
          max(some_data$lon),
          max(some_data$lat)
        ) %>%
        addMarkers(
          lng = ~lon,
          lat = ~lat,
          clusterOptions = markerClusterOptions(
            iconCreateFunction = JS(paste0("function(cluster) {",
                                           "return new L.DivIcon({",
                                           "html: '<div style=\"background-color:rgba(77,77,77,0.5)\"><span>' + cluster.getChildCount() + '</div><span>',",
                                           "className: 'marker-cluster'",
                                           "});",
                                           "}"))



          )
        )
    )
  })

  observeEvent(input$my_button1,{
      leafletProxy(mapId = "map",
                   session = session,
                   data = some_data) %>%
        addProviderTiles(providers$CartoDB.Positron) %>%
        clearMarkerClusters() %>%
        clearMarkers() %>%
        fitBounds(
          min(some_data$lon),
          min(some_data$lat),
          max(some_data$lon),
          max(some_data$lat)
        ) %>%
        addMarkers(
          lng = ~lon,
          lat = ~lat,
          clusterOptions = markerClusterOptions(
            iconCreateFunction = JS(paste0("function(cluster) {",
                                           "console.log('Here comes cluster',cluster); ",
                                           "return new L.DivIcon({",
                                           "html: '<div style=\"background-color:rgba(77,77,77,0.5)\"><span>' + cluster.getChildCount() + '</div><span>',",
                                           "className: 'marker-cluster'",
                                           "});",
                                           "}"))
          )
        )
  })

  observeEvent(input$my_button2,{
    output$map <- renderLeaflet({

      leaflet(data = some_data) %>%
        addProviderTiles(providers$CartoDB.Positron) %>%
        fitBounds(
          min(some_data$lon),
          min(some_data$lat),
          max(some_data$lon),
          max(some_data$lat)
        ) %>%
        addMarkers(
          lng = ~lon,
          lat = ~lat,
          clusterOptions = markerClusterOptions(
            iconCreateFunction = JS(paste0("function(cluster) {",
                                           "console.log('Here comes cluster',cluster); ",
                                           "return new L.DivIcon({",
                                           "html: '<div style=\"background-color:rgba(77,77,77,0.5)\"><span>' + cluster.getChildCount() + '</div><span>',",
                                           "className: 'marker-cluster'",
                                           "});",
                                           "}"))
          )
        )
    })
  })
}

shinyApp(ui = ui, server = server)

软件包版本:

dplyr_0.7.4
leaflet_1.1.0
shiny_1.0.5
R version 3.4.3 (2017-11-30)
Platform: x86_64-pc-linux-gnu (64-bit)
Running under: Ubuntu 16.04.3 LTS

浏览器版本:Firefox Quantum 57.0.1(64 位)

【问题讨论】:

  • 我在运行您的代码时没有收到任何错误。不过我在 Mac 上。
  • 按下两个按钮时您会看到标记吗?感谢您的尝试。
  • 第一次按leafletProxy()后是,但不是在缩小后
  • 谢谢。这正是问题所在。 markercluser 插件应该组织缩放,但在leafletProxy 的情况下,这似乎不起作用(当然,向地图动态添加标记会非常有用)。
  • 这个未得到答复的question 表明这个问题已经存在了一段时间,并且在两个相关的 github 问题(420440)中被引用,那里的团队没有发表评论。

标签: javascript r shiny leaflet leaflet.markercluster


【解决方案1】:

修改后的解决方案

iconCreateFunction 的行为在 leafletProxy 中使用时绝对是 flakey。虽然我认为某些浏览器中存在缓存,因此难以直观地跟踪。

为了消除您遇到的 javascript 错误,应用layerIdclusterId 值以及使用removeMarker 代替clearMarkers 非常重要。

注意我的解决方案的一个奇怪的副作用是重新绘制时会掉下一个标记,我有点累了,稍后再看看。这个问题可能是微不足道的,也可能不是微不足道的。

app.R

library(shiny)
library(dplyr)
library(leaflet)

ui <- fluidPage(
  titlePanel("Hello Shiny!"),
  sidebarLayout(
    sidebarPanel(
      actionButton(inputId = "my_button1",
                   label = "Use leafletProxy()"),
      actionButton(inputId = "my_button2",
                   label = "Use renderLeaflet()")
    ),
    mainPanel(
      leafletOutput(
        outputId = "mymap",
        width = "100%",
        height = "300px"
    ))
))

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

  some_data <- data.frame(
    lon = c(4.905167, 4.906357, 4.905831),
    lat = c(52.37712, 52.37783, 52.37755),
    number_var = c(5, 9, 7),
    name = c("Jane", "Harold", "Mike"),
    stringsAsFactors = FALSE
  )

  marker_js <- JS("function(cluster) {
                  var html = '<div style=\"background-color:rgba(77,77,77,0.5)\"><span>' + cluster.getChildCount() + '</div><span>'
                  return new L.DivIcon({html: html, className: 'marker-cluster'});
                  }")

  output$mymap <- renderLeaflet({

    leaflet(some_data) %>%
      addProviderTiles(providers$CartoDB.Positron) %>%
      fitBounds(
        ~min(lon),
        ~min(lat),
        ~max(lon),
        ~max(lat)
      ) %>%
      addMarkers(
        layerId = "mylayer",
        clusterId = "mycluster",
        lng = ~lon,
        lat = ~lat,
        clusterOptions = markerClusterOptions(
          iconCreateFunction = marker_js
        )
      )

  })

  observeEvent(input$my_button1, {

    leafletProxy("mymap", data = some_data) %>%
      removeMarker(layerId = "mylayer") %>%
      clearTiles %>%
      addProviderTiles(providers$CartoDB.Positron) %>%
      fitBounds(
        ~min(lon),
        ~min(lat),
        ~max(lon),
        ~max(lat)
      ) %>%
      addMarkers(
        layerId = "mylayer",
        clusterId = "mycluster",
        lng = ~lon,
        lat = ~lat,
        clusterOptions = markerClusterOptions(
          iconCreateFunction = marker_js
        )
      )

  })

  observeEvent(input$my_button2,{

    output$mymap <- renderLeaflet({

      leaflet(some_data) %>%
        addProviderTiles(providers$CartoDB.Positron) %>%
        fitBounds(
          ~min(lon),
          ~min(lat),
          ~max(lon),
          ~max(lat)
        ) %>%
        addMarkers(
          layerId = "mylayer",
          clusterId = "mycluster",
          lng = ~lon,
          lat = ~lat,
          clusterOptions = markerClusterOptions(
            iconCreateFunction = marker_js
          )
        )
    })

  })

}

shinyApp(ui = ui, server = server)

浏览器内

没有发现其他 javascript 错误。

【讨论】:

  • 感谢您的意见;我同意在使用leafletProxy() 操作之前应该初始化和预渲染传单地图。然而我的主要问题仍然存在:使用leafletProxy() 时插件不接受选项iconCreateFunction 的自定义函数。我认为这是一个错误,除非我知道如何为使用 leafletProxy() 注入的标记使用自定义创建函数。
  • @nilsole,根据您的说明更新解决方案。
  • 谢谢。上面的代码会导致错误。 1)运行应用程序。 2) 打开开发者工具/Firebug。 3) 点击“使用leafletProxy()”。 4) 如上所述的JS错误:Uncaught TypeError: this._group.options.iconCreateFunction is not a function。请问可以复制吗?
  • 几乎完美,干得好。剩下的唯一问题是:为什么刷新的代理地图只添加了 2 个点而不是 3 个?似乎缺少一个标记。我尝试在刷新时更改layerIdclusterId,但没有任何积极效果。
  • 我认为这变成了从这里开始的推测性讨论,因此请为您的发现和研究获得奖励(我很抱歉我没有提供链接,抱歉)。
【解决方案2】:

按照 Kevin 的回答,将 clusterId 修改为向量可以让 leafletProxy 版本为我工作。不确定这是否会导致意想不到的后果......

app.R

library(shiny)
library(dplyr)
library(leaflet)

ui <- fluidPage(
  titlePanel("Hello Shiny!"),
  sidebarLayout(
    sidebarPanel(
      actionButton(inputId = "my_button1",
                   label = "Use leafletProxy()"),
      actionButton(inputId = "my_button2",
                   label = "Use renderLeaflet()")
    ),
    mainPanel(
      leafletOutput(
        outputId = "mymap",
        width = "100%",
        height = "300px"
      ))
  ))

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

  some_data <- data.frame(
    lon = c(4.905167, 4.906357, 4.905831),
    lat = c(52.37712, 52.37783, 52.37755),
    number_var = c(5, 9, 7),
    name = c("Jane", "Harold", "Mike"),
    stringsAsFactors = FALSE
  )

  marker_js <- JS("function(cluster) {
                  var html = '<div style=\"background-color:rgba(77,77,77,0.5)\"><span>' + cluster.getChildCount() + '</div><span>'
                  return new L.DivIcon({html: html, className: 'marker-cluster'});
}")

  output$mymap <- renderLeaflet({

    leaflet(some_data) %>%
      addProviderTiles(providers$CartoDB.Positron) %>%
      fitBounds(
        ~min(lon),
        ~min(lat),
        ~max(lon),
        ~max(lat)
      ) %>%
      addMarkers(
        layerId = "mylayer",
        clusterId = "mycluster",
        lng = ~lon,
        lat = ~lat,
        clusterOptions = markerClusterOptions(
          iconCreateFunction = marker_js
        )
      )

  })

  observeEvent(input$my_button1, {

    leafletProxy("mymap", data = some_data) %>%
      removeMarker(layerId = "mylayer") %>%
      clearTiles %>%
      addProviderTiles(providers$CartoDB.Positron) %>%
      fitBounds(
        ~min(lon),
        ~min(lat),
        ~max(lon),
        ~max(lat)
      ) %>%
      addMarkers(
        layerId = "mylayer",
        clusterId = ~name,
        lng = ~lon,
        lat = ~lat,
        clusterOptions = markerClusterOptions(
          iconCreateFunction = marker_js
        )
      )

  })

  observeEvent(input$my_button2,{

    output$mymap <- renderLeaflet({

      leaflet(some_data) %>%
        addProviderTiles(providers$CartoDB.Positron) %>%
        fitBounds(
          ~min(lon),
          ~min(lat),
          ~max(lon),
          ~max(lat)
        ) %>%
        addMarkers(
          layerId = "mylayer",
          clusterId = "mycluster",
          lng = ~lon,
          lat = ~lat,
          clusterOptions = markerClusterOptions(
            iconCreateFunction = marker_js
          )
        )
    })

  })

  }

shinyApp(ui = ui, server = server)

【讨论】:

    猜你喜欢
    • 2014-11-12
    • 1970-01-01
    • 2016-02-06
    • 2010-12-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-13
    • 2018-12-15
    相关资源
    最近更新 更多