Кластерные маркеры для листовок с итоговыми суммами (не в счетах): как получить согласованную круглую красную форму и формат этикетки, как в некластеризованных маркерах - PullRequest
0 голосов
/ 14 февраля 2020

Я хотел бы изменить поведение функции группировки листовок для суммирования при группировке и сохранить круглую форму красного пузыря в зависимости от значения.

Мои данные содержат столбцы:

lon lat sales_ytd

Я хотел бы кластеризовать данные в зависимости от масштаба с использованием clusterOption s = markerClusterOptions (iconCreateFunction = JS (sum.formula)

1010 * Вот моя функция. Я не знаю 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 () возвращает квадрат ... есть ли способ вернуть ему круглый красный пузырь?

Тогда я пытаюсь использовать его в блестящем приложении (код 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)))
})

Grouped markers

Группировка несколько работает, значения суммируются для кластеризованных данных, и, если я щелкну по ним, листовка увеличится и покажет отдельные точки (красивые красные кружки со значениями внутри). Но сгруппированные маркеры - это белые квадраты, а не круглые красные круги, как отдельные точки. Также я не знаю, как добиться согласованного форматирования для чисел. В R это просто, но определение сгруппированных маркеров теперь в JS. Как этого достичь: согласованная форма, цвет и размер, зависящие от значения как в несгруппированных, так и сгруппированных маркерах, и согласованные числовые форматы ? Можно также увидеть Я попытался нормализовать размер в R, и я разделил size / 1000 на JS - я не знал, как передать сумму столбца data.frame в JS.

Ответы [ 2 ]

2 голосов
/ 20 февраля 2020

Для общего количества маркеров / слоев вы можете использовать функцию getLayers (), которая будет возвращать массив всех компонентных слоев этого кластера.

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

Она будет возвращать массив каждого маркера в качестве слоя .

В качестве альтернативы Вы можете использовать это:

map.eachLayer(function (layer) {
        if (layer.getChildCount){     
            console.log(layer._childClusters.length)        
            console.log(layer._childCount);  
            }
    });
1 голос
/ 21 февраля 2020

Вы можете попробовать настроить пользовательскую функцию sum.formula, чтобы добавить класс CSS к маркеру, который затем можно настроить, а также отформатировать число, чтобы добавить тысячи разделителей.

Я добавил Пример MWE ниже, я добавил класс custom-cluster-icon к значкам и отформатировал числа, используя регулярное выражение в этой записи .

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)
...