trafficonese / leaflet.extras

Extra functionality for leaflet R package.
https://trafficonese.github.io/leaflet.extras/
GNU General Public License v3.0
211 stars 74 forks source link

Feature request: Clustered leaflet markers with sum (not count) totals, consistent shapes, sizes and label formats. #191

Open jacekkotowski opened 4 years ago

jacekkotowski commented 4 years ago

This request is repeated from https://github.com/rstudio/leaflet/issues/672?fbclid=IwAR1i-PuUMtH_gHGT7ISUp86_BUd2NgVV6nlHuopb-oX0g3oQ87kVeNa9ZAE Please close/delete if you find it not appropriate, I put it here presuming that leaflet.extras may be a good place to address this request.

I would like to propose an extension of behavior of leaflet grouping feature for bubble plots: to total (sum, not count) on grouping and preserve a round red bubble shape dependent on value and consistent number format for text label. I asked a question about that at https://stackoverflow.com/questions/60226819/clustered-leaflet-markers-with-sum-not-count-totals-how-to-get-consistent-rou/60310097?noredirect=1#comment106752233_60310097 first. The solution required some JS and CSS tinkering and it is almost there but during zooming the sizes are still not consistent. It may perhaps better be corrected by a person more knowlegable in JS and may be easily corrected by the authors.

Instead of minimal reprex I described the problem on stackoverflow and there is a proposed solution almost there: https://stackoverflow.com/questions/60226819/clustered-leaflet-markers-with-sum-not-count-totals-how-to-get-consistent-rou/60310097?noredirect=1#comment106752233_60310097

# the solutinon, author NicE (lots of respect for helping me out): https://stackoverflow.com/users/4474157/nice

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)

I believe bubble plots clustering on sums of bubble attribute (on a variable, column name) and not counts of sub-bubbles, with consistent sizes dependent on value, consistent number format for text labels (the same for unclustered and clustered bubbles, would be very beneficial for all users not only for my case. It will greatly improve clarity of bubble plots on zoomed maps.

Some links I have followed to solve the issue, I thought may give me a hint how to solve the issue: https://github.com/Leaflet/Leaflet.markercluster#customising-the-clustered-markers https://stackoverflow.com/questions/27486893/how-to-display-the-value-sum-rather-than-count-of-markers-in-a-dc-leaflet-js https://github.com/Leaflet/Leaflet.markercluster/issues/363

The issue was asked for by others on leaflet's github: https://github.com/Leaflet/Leaflet.markercluster/issues/363#issuecomment-288329002