具有总和(不是计数)总计的聚类传单标记:如何像非聚类标记一样获得一致的圆形红色和标签格式

Clustered leaflet markers with sum (not count) totals: how to get consistent round red shape and label format like in unclustered markers

我想将传单分组功能的行为修改为总计分组,并根据值保留圆形红色气泡形状。

我的数据包含列:

经纬度sales_ytd

我想使用 clusterOptions = markerClusterOptions(iconCreateFunction=JS(sum.formula))

根据缩放对数据进行聚类

这是我的功能。我不懂 JS,但我尝试了很多示例,该函数通过对分组值求和来工作。

 sum.formula  = JS("function (cluster) {    
        var markers = cluster.getAllChildMarkers();
        var sum = 0; 
        for (i = 0; i < markers.length; i++) {
          sum += Number(markers[i].options.mag);
    //      sum += 1;
        }
          var size = sum/30000;

        return new L.DivIcon({ html:  sum ,  iconSize: L.point(size, size)});
      }")

显然L.DivIcon() return是一个正方形... 有没有办法让它return变成圆形的红色气泡?

然后我尝试在闪亮的应用程序(R 代码)中使用它。

renderLeaflet({
  leaflet(df_summary_towns()) %>% 
  addTiles() %>%
  addCircleMarkers(
    radius = ~sales_ytd/30000,
    color = 'red',
    stroke = FALSE, 
    fillOpacity = 0.5,
    options = markerOptions(mag = ~ sales_ytd),
    clusterOptions = markerClusterOptions(iconCreateFunction=JS(sum.formula))
  ) %>% 
    addLabelOnlyMarkers(
      ~lon, ~lat, 
      options = markerOptions(mag = ~ sales_ytd),
      label =  ~scales::number(sales_ytd),
      labelOptions = labelOptions(noHide = T, direction = 'center', textOnly = T),
      clusterOptions = markerClusterOptions(iconCreateFunction=JS(sum.formula)))
})

分组有点奏效,值是聚集数据的总和,如果我单击它们,传单会缩放并显示单个点(漂亮的红色圆圈,里面有值)。但是分组标记是白色方块,而不是像单个点那样的圆形红色圆圈。我也不知道如何实现一致的数字格式。在 R 中很容易,但分组标记的定义现在在 JS 中。 如何实现:形状、颜色和大小取决于未分组和分组标记中的值以及一致的数字格式? 还可以看到 我尝试在 R 中规范化大小,然后在 JS 中划分 size/1000 - 我不知道如何将 data.frame 列的总和传递给 JS.

对于 markers/layers 的总数,您可以使用 getLayers() 函数,它将 return 该集群的所有组件层的数组。

var testCluster = L.markerClusterGroup();
L.marker([event.latlng.lat, 
event.latlng.lng]).addTo(testCluster);
testCluster.getLayers();

它将return每个标记的数组作为图层。

或者你可以使用这个:

map.eachLayer(function (layer) {
        if (layer.getChildCount){     
            console.log(layer._childClusters.length)        
            console.log(layer._childCount);  
            }
    });

您可以尝试调整自定义 sum.formula 函数以将 CSS class 添加到您可以自定义的标记,以及格式化数字以添加千位分隔符。

我在下面添加了一个 MWE 示例,我在图标中添加了 custom-cluster-icon class,并使用 this post 中的正则表达式格式化了数字。

闪亮页面页眉中包含的 CSS 以及在 sum.formula 输出中添加的行有助于使标签居中,并添加红色标记圆圈。

library(leaflet)
library(shiny)

#dummy data for example
df_summary_towns=quakes
df_summary_towns$sales_ytd=sample(2000:5000,1000)

sum.formula  = JS("function (cluster) {    
    var markers = cluster.getAllChildMarkers();
    var sum = 0; 
    for (i = 0; i < markers.length; i++) {
      sum += Number(markers[i].options.mag);
    }
      var size = sum/10000;
      var formatted_number = Math.round(sum).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ' ');

    return new L.DivIcon({ className: 'custom-cluster-icon', html: '<div style=\"line-height:'+size+'px; white-space: nowrap;\">'+formatted_number+'</div>'   , iconSize: L.point(size, size) });
  }")


ui <- fluidPage(
  tags$head(
    tags$style(HTML("
      .custom-cluster-icon {
        background: rgba(255, 0, 0, 0.3);
        border-radius: 50%;
        text-align: center;
      }
      "))
  ),
  leafletOutput("mymap")
)

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

  points <- eventReactive(input$recalc, {
    cbind(rnorm(40) * 2 + 13, rnorm(40) + 48)
  }, ignoreNULL = FALSE)

  output$mymap <- renderLeaflet({
    leaflet(df_summary_towns) %>% 
      addTiles() %>%
      addCircleMarkers(
        radius = ~sales_ytd/10000,
        color = 'red',
        stroke = FALSE, 
        fillOpacity = 0.5,
        options = markerOptions(mag = ~ sales_ytd, min_sales =  ~min(sales_ytd), max_sales = ~ max(sales_ytd)),
        clusterOptions = markerClusterOptions(iconCreateFunction=JS(sum.formula))
      ) %>% 
      addLabelOnlyMarkers(
        ~long, ~lat, 
        options = markerOptions(mag = ~ sales_ytd),
        label =  ~scales::number(sales_ytd),
        labelOptions = labelOptions(noHide = T, direction = 'center', textOnly = T),
        clusterOptions = markerClusterOptions(iconCreateFunction=JS(sum.formula)))
  })
}

shinyApp(ui, server)