folium
folium copied to clipboard
LayerGroup support
Short question
Will Folium ever allow a generation of LayerGroup, or a decision had been made to keep only FeatureGroup?
Details
According to LeafletJS documentation, FeatureGroup extends LayerGroup. They have different JS constructors:
L.featureGroup(<Layer[]> layers)
with only a list of layers,
L.layerGroup(<Layer[]> layers?, <Object> options?)
with some options in addition to layers.
When creating a FeatureGroup in Folium, there is a parameter name
in its Python constructor (as well as some visualization-related params):
__init__(self, name=None, overlay=True, control=True, show=True)
However, this name
is only used to display a name of this featuregroup in a LayerControl:
var feature_group_bdeeee... = L.featureGroup(name="events").addTo(map_...);
var layer_control_... = {
base_layers : { "openstreetmap" : ...},
overlays : { "events" : feature_group_bdeeee... }
}
What I need to have in a generated code for my use-case is a constructor with those options parameter, proposed by LayerGroup:
var layer_group_2... = L.layerGroup(null, {'step': '2'})
This would allow to access those attributes (step in my example) of my featuregroup (layergroup) using some custom JS code to put listeners on some objects.
Example of use case: when hovering step=5
name in a custom div
element, 5th circle from events
group and 5th marker of another (say, places
) group change their CSS classes to highlight the connection between 5th "event" and "place", a bit like zip
in Python.
To make it possible, i need L.layerGroup(null, {'step': '1'})
generated code instead of just empty L.featureGroup()
. I could write corresponding code and make a PR, if ever this functionality is welcomed by the community :-)
folium version 0.7.0.
Sorry if anything is unclear, this is the 1st issue i open. Don't hesitate to ask for more details. Thanks!
Hi @denisflash, I don’t think there was ever a conscious decision not to add layergroup. So we can definitely consider adding it. I don’t really understand your example though. Could you explain a bit more why you need layergroup, and featuregroup doesn’t work for you?
I’m thinking now that adding this might help with some of the issues we’ve been having with the grouping of geojson layers. So if someone wants to pick this up that would be great. Should be straightforward to duplicate the current featuregroup implementation and alter it.
Thanks a lot, @Conengmo ! Sorry for the late answer.
As I said, what I need is that Folium generate a JS object that can accept some custom parameters. I will later have some JS script that will use those parameters to do some CSS magic for my use case. LayerGroup has custom parameters, while FeatureGroup does not.
This is the shortest and the most generic explanation I could give. Tell me if you want more details, I could potentially explain a bit more on what I mean by step: 1
, step: 2
in the example I gave above.
Great! I will try to pick this issue up. It could take some time however (the "onboarding" part: setting up the environment, launching tests, etc. etc., before even diving into the code itself), as this will be my first contribution to Folium. Thanks for putting badges on this issue! :-)
While trying to do the dev, I note the following:
-
Implementing LayerGroup class by copying and modifying FeatureGroup and its template is quite easy; I already have a simple LayerGroup implementation and could push it. However, it will not solve my problem (see below).
-
More tricky (and almost blocking for my use case) is the fact that
branca.element.Element
can only have one parent in its._parent
attribute. When doing something likeMarker(...).add_to(feature_group_1).add_to(layer_group_1)
, only the lastadd_to
is taken into account (it overwrites element's parent). When creating this issue, i thought having LayerGroup with options/attributes dictionary can solve my problem, but it appears to be insufficient, since i need elements to have multiple parents. Which looks like a potentially huuuge modification affecting not only a lot of classes in Folium repository, but even Branca repository. To have a "green light", this type of modifications would certainly require a lot of discussions inside the community.
Another solution for my problem (without touching number of parents) would be to pass custom attributes to elements themselves (Circle
and other folium.vector_layers.*
elements). But then, the problem is that on the LeafletJS side, there is no support for elements' attributes (while L.LayerGroup
does accept options
object, L.Layer
class does not).
So looks like the only way to pass some custom attributes to vector layer's elements is through adding a popup. Theoretically we could then parse those popups with a piece of custom JS on our "user" side. It could theoretically solve our problem without changing anything inside Folium. We will have to write that custom JS and accept our popups to be quite clumsy.
@Conengmo , tell me if you think that pushing LayerGroup will at least be useful for your case:
"adding this might help with some of the issues we’ve been having with the grouping of geojson layers"
If it is, i will create a PR. Thanks!
I don't really understand what you are trying to achieve to be honest.
Letting an Element have multiple parents is an interesting proposal. It would allow for a popup to be applied to multiple features for example, quite useful. I don't think a lot of discussion is needed for this. But we do need to be sure what the side effects are.
If you still want to push a PR simply implementing LayerGroup
that's welcome! Please include:
- the actual change
- a test to verify the template rendering correctly
- ideally an example notebook showing the difference between
FeatureGroup
andLayerGroup
.
Thanks for a fast response, Frank. Ok, I think I should give more details to be clear about the main reason I created this issue.
Some time ago my colleague had written a custom Python wrapper for Leaflet. In my opinion, using Folium would give us more possibilities, moreover it is stable, open source and maintained by the community. Having custom code will be quite difficult to maintain/evolve. So I started investigating why he decided to write this custom framework, instead of just using Folium. As the guy has already left the team, I don't have a 100% clear answer. But it looks like there were 2 reasons:
-
Technical. Code generated by Folium was more verbose than generated with his custom tool, see my comment showing that difference (an example I give at the end of that comment looks almost as what his tool generates).
-
Functional. And this is the main reason I created this issue. He created something called "trace", which does the following. Imagine a sequence of Circle elements, with timestamp associated to each of them. There is also a
on the generated HTML which gives an ordered list of those timestamps. Mouse hover event on any circle draws a rectangle around it, and highlights in that "trace div" theelement corresponding to hovered circle. And vice versa: hovering on any of "trace div" draws a rectangle around the circle linked to this . This is simply a CSS mechanism, which is enabled by the ability to pass custom parameters to a LayerGroup that will link a circle and a in trace div. So for our example we would have 1 FeatureGroup
(let's say, "circles"), and NLayerGroups
(where N is the number of circles) that looks something like that:var lay_1 = L.layerGroup(null, {'step': '1', 'label': '2018-01-02 12:34:56'}
(Today, we cannot generate a line like that using Folium's
FeatureGroup
, as it does not accept parameters).Then we add each circle to its corresponding
LayerGroup
, and the layergroup'sstep
attribute allows us to do our custom CSS stuff. But as each circle is also a part of a "circles" FeatureGroup, it would mean we need each circle to have two parents: "circles" FeatureGroup and itslay_x
LayerGroup where "x" is replaced by the position of a circle in the sequence (step
attribute).Hope this makes more sense.
Thanks for explaining, I do get it better now. If you open a PR we can look at what’s possible without overcomplicating the class. You can always add additional functionality by adding some custom Javascript.
Any updates on this? I also believe this would be a great piece of functionality - as of today only one choropleth can be used, having multiple layers would benefit many folks
If we adopt LayerGroup, I think we should be able to explain to our users what the difference with FeatureGroup is. As I see it now, in folium it doesn't really make a difference in practice. We don't use any of the distinguishing features of FeatureGroup: https://leafletjs.com/reference.html#featuregroup. Grouping GeoJsons already works fine with FeatureGroup. The issue with Choropleth grouping is not the FeatureGroup, but the fact that colorscales are placed absolutely, outside of Leaflet.
I see three options at the moment:
- Don't adopt LayerGroup, keep the focus on FeatureGroup as we have always done.
- Adopt LayerGroup silently for the benefit of advanced users.
- Someone reply in this issue why I'm wrong and what the folium use case for LayerGroup is :)
Hi everyone, As for myself, unfortunately i'm not working on that project anymore, the one where i had the use case i described back in 2019. So i will not be able to continue neither the implementation work, nor discussing the technical decisions. The reason: the use case is not there anymore.
So, @gloriamacia , if you're currently working on a related topic and will benefit from this new feature, i guess it would be more convenient if you take it over and describe to the team, what your needs are.
I'll continue following the topic though. Thanks guys!
p.s. sorry for closing and reopening, just a misclick.