0

I'm using leaflet and shiny to create a small map with clusters. For that, I need to change the colours of the clusters, which I've done using code from a reply to this question. However, I cannot get it to work within leafletProxy(), which I need in order to allow the user to filter the data being displayed. Here is an example that shows the problem (I've just coloured all the clusters red):

library(shiny)
library(leaflet)

ui <- fluidPage(
    tags$head(tags$style(HTML("
                              .marker-custom-small {
                              background-color: rgba(255, 0, 0, 1);
                              }
                              .marker-customr-small div {
                              background-color: rgba(255, 0, 0, 1);
                              }

                              .marker-custom-medium {
                              background-color: rgba(255, 0, 0, 1);
                              }
                              .marker-custom-medium div {
                              background-color: rgba(255, 0, 0, 1);
                              }

                              .marker-custom-large {
                              background-color: rgba(255, 0, 0, 1);
                              }
                              .marker-custom-large div {
                              background-color: rgba(255, 0, 0, 1);
                              }"))),
    actionButton("but", "New clusters, please!"),

    leafletOutput("mymap")


  )

  server<-function(input, output, session) {
    output$mymap <- renderLeaflet({
      leaflet(quakes) %>% addTiles() %>% addMarkers(
        clusterOptions = markerClusterOptions(iconCreateFunction=JS("function (cluster) {    
                                                                    var childCount = cluster.getChildCount(); 
                                                                    var c = ' marker-custom-';  
                                                                    if (childCount < 100) {  
                                                                    c += 'large';  
                                                                    } else if (childCount < 1000) {  
                                                                    c += 'medium';  
                                                                    } else { 
                                                                    c += 'small';  
                                                                    }    
                                                                    return new L.DivIcon({ html: '<div><span>' + childCount + '</span></div>', className: 'marker-cluster' + c, iconSize: new L.Point(40, 40) });

    }"))
    )
  })


    observeEvent(input$but, {

      leafletProxy("mymap") %>%

      clearMarkerClusters() %>%

        addMarkers(data = quakes,
          clusterOptions = markerClusterOptions(iconCreateFunction=JS("function (cluster) {    
                                                                      var childCount = cluster.getChildCount(); 
                                                                      var c = ' marker-custom-';  
                                                                      if (childCount < 100) {  
                                                                      c += 'large';  
                                                                      } else if (childCount < 1000) {  
                                                                      c += 'medium';  
                                                                      } else { 
                                                                      c += 'small';  
                                                                      }    
                                                                      return new L.DivIcon({ html: '<div><span>' + childCount + '</span></div>', className: 'marker-cluster' + c, iconSize: new L.Point(40, 40) });

                }"))
        )




    })


  }

  shinyApp(ui,server)

When the user clicks the button, new clusters (of the same points, in this example) should be displayed, but nothing happens. R reports no errors, and the quakes data is being read by addMarkers(), because I get the message Assuming 'long' and 'lat' are longitude and latitude, respectively in the console. I suspect the problem has to do with the addMarkers() call inside leafletProxy() not finding(?) the cluster classes, because replacing...

clusterOptions = markerClusterOptions(iconCreateFunction=JS("function (cluster) {    
                                                            var childCount = cluster.getChildCount(); 
                                                            var c = ' marker-custom-';  
                                                            if (childCount < 100) {  
                                                            c += 'large';  
                                                            } else if (childCount < 1000) {  
                                                            c += 'medium';  
                                                            } else { 
                                                            c += 'small';  
                                                            }    
                                                            return new L.DivIcon({ html: '<div><span>' + childCount + '</span></div>', className: 'marker-cluster' + c, iconSize: new L.Point(40, 40) });

                                                            }"))

with just...

clusterOptions = markerClusterOptions()

...makes the clusters - with the standard colours - display just fine.

I would greatly appreciate some help on this!

Best,

Bertel

Community
  • 1
  • 1
Bertel
  • 121
  • 1
  • 3

1 Answers1

1

Following the advice on the Shiny articles site here I managed to get this to work using a custom stylesheet linked to in ui.R with the includeCSS() function. I haven't used any JS expressions when adding clusters and my custom colour(s) are coming through just fine.

For example, the code:

library(shiny)
library(leaflet)

ui <- fluidPage(
    includeCSS("./style.css"),

    actionButton("but", "New clusters, please!"),

  leafletOutput("mymap")


  )

server<-function(input, output, session) {
  output$mymap <- renderLeaflet({
    leaflet(quakes) %>% addTiles() %>% addMarkers(clusterOptions =
                                                    markerClusterOptions())
})


  observeEvent(input$but, {

    leafletProxy("mymap") %>%

      clearMarkerClusters() %>%

      addMarkers(data = quakes,
                 clusterOptions = markerClusterOptions())
  })


}

shinyApp(ui,server)

Should work, you just need to make sure you fully specify all styles that are defined in the default styling (found in ./path/to/your/package/library/leaflet/htmlwidgets/plugins/Leaflet.markercluster/MarkerCluster.Default)

For example, to colour all clusters red (as per your original example), you can use:

style.css:

.marker-cluster-small {
    background-color: rgba(255, 0, 0, 1);
    }
.marker-cluster-small div {
    background-color: rgba(255, 0, 0, 1);
    }

.marker-cluster-medium {
    background-color: rgba(255, 0, 0, 1);
    }
.marker-cluster-medium div {
    background-color: rgba(255, 0, 0, 1);
    }

.marker-cluster-large {
    background-color: rgba(255, 0, 0, 1);
    }
.marker-cluster-large div {
    background-color: rgba(255, 0, 0, 1);
    }

    /* IE 6-8 fallback colors */
.leaflet-oldie .marker-cluster-small {
    background-color: rgb(255, 0, 0);
    }
.leaflet-oldie .marker-cluster-small div {
    background-color: rgb(255, 0, 0);
    }

.leaflet-oldie .marker-cluster-medium {
    background-color: rgb(255, 0, 0);
    }
.leaflet-oldie .marker-cluster-medium div {
    background-color: rgb(255, 0, 0);
    }

.leaflet-oldie .marker-cluster-large {
    background-color: rgb(255, 0, 0);
    }
.leaflet-oldie .marker-cluster-large div {
    background-color: rgb(255, 0, 0);
}

.marker-cluster {
    background-clip: padding-box;
    border-radius: 20px;
    }
.marker-cluster div {
    width: 30px;
    height: 30px;
    margin-left: 5px;
    margin-top: 5px;

    text-align: center;
    border-radius: 15px;
    font: 12px "Helvetica Neue", Arial, Helvetica, sans-serif;
    }
.marker-cluster span {
    line-height: 30px;
    }

This should allow you to fully customise the clusters, and have them be correctly displayed when you use leafletProxy().

Jim Leach
  • 449
  • 5
  • 7