rstudio / leaflet

R Interface to Leaflet Maps
http://rstudio.github.io/leaflet/
Other
805 stars 508 forks source link

[feature request] setStyle (dynamic styles without resending entire Vector layers) #152

Open chris-holcomb opened 9 years ago

chris-holcomb commented 9 years ago

It would be awesome to have some way to interactively change the styles of individual features of GeoJSON objects (and possibly other vector layers) without having to remove and re-add the entire layer. FWIW it appears this works for TopoJSON as well: http://gis.stackexchange.com/questions/120012/leaflet-omnivore-style-function. The final answer on this question (http://gis.stackexchange.com/questions/75590/setstyle-function-for-geojson-features-leaflet) included this:

geojson_layer.eachLayer(function (layer) {  
  if(layer.feature.properties.NAME == 'feature 1') {    
    layer.setStyle({fillColor :'blue'}) 
  }
});

As this is my first exposure to this method, I don't have detailed recommendations on how to implement this yet. I can describe my use case - I'm dynamically calculating some values in R that are used to color GeoJSON features, so right now I'm removing the GeoJSON and adding back a GeoJSON with the new styles upon each calculation. BTW, the jsonlite and RJSONIO toJSON functions are very slow for converting back to GeoJSON after manipulating the data as an R list (takes around 15 seconds for a 1MB GeoJSON with only id's and simplified shapes), so I am actually parsing the GeoJSON as text and inserting the styles (0.3 seconds).

chris-holcomb commented 9 years ago

An example that shows setStyle as well as resetStyle is at http://leafletjs.com/examples/choropleth.html. This also shows the excellent speed improvements of mouseover, mouseout, and click that can occur if that's done without R intercepting (is there a way to input arbitrary JS functions for these events for each layer?). Note: the ability to color the borders quickly is critical because with colored polygons may obfuscate the border (this definitely happens for multi-polygons).

I edited the prior example to include the aforementioned code to turn Texas blue (it changes back after a mouseout) into this jsfiddle (removed some code from original example): http://jsfiddle.net/7xqt2crh/2/.

Please note: the feature request differs from this - we need a way to send over an updated style to a specific feature after an event occurs in Shiny with style information passed to Leaflet from Shiny. We also need to style with other parameters such as fillColor, etc.

ADDED:

A simple set_style(layer, id, style) where style is in JSON and id is the name of a required property in the object to search for would work as a stop-gap. Of course you may want to send over a function to run that has all the if/else conditions instead of sending separate requests for loops. I set up a jsfiddle (http://jsfiddle.net/2j7p9m91/) with both that might help for testing (but it's only 50 features). It turns the states blue with separate if statements first and then turns them red with one massive if/else statement. In the latter case you could have set_styles(layer,ids,styles) where ids and styles are character vectors. For set_style you could also have the option for id = NULL to change the style for all the features to the same style via setStyle (instead of wrapping it in eachLayer).

You could also have set_style_sets(layer, id_set [character vector], style) to use the same style for different ids. Then maybe, set_styles_sets(layer, id_sets [list of character vectors], styles) to use different styles for each array of ids.

timelyportfolio commented 9 years ago

:+1:

jcheng5 commented 9 years ago

Really nice idea...

mbacou commented 9 years ago

Yes, ran into that use case yesterday. Restyling/re-using layers is very common scenario.

chris-holcomb commented 9 years ago

FWIW, I made a branch with a simplified version of some of these capabilities and included a new example utilizing them. I'm on vacation now but may clean them up further and send over a PR once I have time. On Aug 3, 2015 1:12 PM, "Melanie Bacou" notifications@github.com wrote:

Yes, ran into that use case yesterday. Restyling/re-using layers is very common scenario.

— Reply to this email directly or view it on GitHub https://github.com/rstudio/leaflet/issues/152#issuecomment-127407528.

ComeMaes commented 7 years ago

Hi @ideamotor and Studio team and community,

Have you worked any further on this? I'd be very interested in such a feature and willing to contribute, as I also feel that it might help in a variety of fairly common scenarios.

timelyportfolio commented 4 years ago

496