Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow GeoJSON to be used with Custom Pane #2028

Open
lukefullard opened this issue Nov 7, 2024 · 8 comments
Open

Allow GeoJSON to be used with Custom Pane #2028

lukefullard opened this issue Nov 7, 2024 · 8 comments

Comments

@lukefullard
Copy link

Is your feature request related to a problem? Please describe.
I can assign a folium marker to a custom pane as in the example below:

import folium
from folium.map import CustomPane
m = folium.Map(location=[51.5074, -0.1278], zoom_start=10)
custom_pane = CustomPane(name='custom_pane', z_index=1000,pointer_events =True)
custom_pane.add_to(m)
marker = folium.Marker([51.5074, -0.1278], popup="This is a custom marker!", pane = "custom_pane")
marker.add_to(m)

However, there is no "pane" argument for folium.GeoJson.
Could this please be added?

Describe the solution you'd like
The ability to add a specific GeoJSON to a custom pane.

Describe alternatives you've considered
I am not sure where to start.

@lukefullard
Copy link
Author

lukefullard commented Nov 7, 2024

Just as a motivation for this, the code below creates a map with a sidebyside layer.
If I assign each layer to a custom pane I can add a marker to one side of the pane and not the other:

import folium
from folium.map import CustomPane
m = folium.Map(location=(30, 20), zoom_start=4)
custom_pane_l = CustomPane(name='left', z_index=1000,pointer_events =True)
custom_pane_l.add_to(m)
custom_pane_r = CustomPane(name='right', z_index=1000,pointer_events =True)
custom_pane_r.add_to(m)
layer_right = folium.TileLayer('openstreetmap', pane='right')
layer_left = folium.TileLayer('cartodbpositron', pane='left')
sbs = folium.plugins.SideBySideLayers(layer_left=layer_left, layer_right=layer_right)
layer_left.add_to(m)
layer_right.add_to(m)
sbs.add_to(m)
marker = folium.Marker([51.5074, -0.1278], popup="This is a custom marker!", pane = "left")
marker.add_to(m)

Resulting in...

image

You can see the map on the left has the marker but does not on the right.

I'd like to be able to do this with polygons, not just markers.

@hansthen
Copy link
Collaborator

hansthen commented Nov 8, 2024

I did not try it yet myself, but I think this should "just work". The pane argument is not explicitly documented on GeoJson (it is inherited from L.Layer).

Could you try it and see what happens?

@lukefullard
Copy link
Author

Unfortunately I get an error:

import folium
from folium.map import CustomPane
import folium.plugins

m = folium.Map(location=(30, 20), zoom_start=4)
custom_pane_l = CustomPane(name='left', z_index=600, pointer_events=True)
custom_pane_l.add_to(m)
custom_pane_r = CustomPane(name='right', z_index=600, pointer_events=True)
custom_pane_r.add_to(m)
layer_right = folium.TileLayer('openstreetmap', pane='right')
layer_left = folium.TileLayer('cartodbpositron', pane='left')
sbs = folium.plugins.SideBySideLayers(layer_left=layer_left, layer_right=layer_right)
layer_left.add_to(m)
layer_right.add_to(m)
sbs.add_to(m)
marker = folium.Marker([51.5074, -0.1278], popup="This is a custom marker!", pane="left")
marker.add_to(m)
geojson_data = {
    "type": "FeatureCollection",
    "features": [
        {
            "type": "Feature",
            "geometry": {
                "type": "Point",
                "coordinates": [-0.1278, 51.5074]
            },
            "properties": {
                "name": "London"
            }
        }
    ]
}

geojson_layer = folium.GeoJson(geojson_data, pane='right', name='GeoJSON Example')
geojson_layer.add_to(m)

throws the error:

_geojson_layer = folium.GeoJson(geojson_data, pane='right', name='GeoJSON Example')

TypeError: GeoJson.init() got an unexpected keyword argument 'pane'_

@hansthen
Copy link
Collaborator

hansthen commented Nov 9, 2024

Strange, I cannot reproduce your error message.

Python 3.10.12 (main, Sep 11 2024, 15:47:36) [GCC 11.4.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import folium
>>> geojson_data = {
...     "type": "FeatureCollection",
...     "features": [
...         {
...             "type": "Feature",
...             "geometry": {
...                 "type": "Point",
...                 "coordinates": [-0.1278, 51.5074]
...             },
...             "properties": {
...                 "name": "London"
...             }
...         }
...     ]
... }
>>> geojson_layer = folium.GeoJson(geojson_data, pane='right', name='GeoJSON Example')
# No errors here

Regardless of the exact message, it does not appear to be working as you want.

@lukefullard
Copy link
Author

Strange, I cannot reproduce your error message.

Python 3.10.12 (main, Sep 11 2024, 15:47:36) [GCC 11.4.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import folium
>>> geojson_data = {
...     "type": "FeatureCollection",
...     "features": [
...         {
...             "type": "Feature",
...             "geometry": {
...                 "type": "Point",
...                 "coordinates": [-0.1278, 51.5074]
...             },
...             "properties": {
...                 "name": "London"
...             }
...         }
...     ]
... }
>>> geojson_layer = folium.GeoJson(geojson_data, pane='right', name='GeoJSON Example')
# No errors here

Regardless of the exact message, it does not appear to be working as you want.

Ah thank you for following up.
I realised that the version could be the issue.
Upgrading from 0.14 to 0.18 did remove the error message, and I can plot a polygon, but unfortunately it is not contained to the right pane:

import folium
from folium.map import CustomPane
from folium.plugins import SideBySideLayers

# Create the map object centered at a specific location
m = folium.Map(location=(30, 20), zoom_start=4)

# Create custom panes for left and right
custom_pane_l = CustomPane(name='left', z_index=1000, pointer_events=True)
custom_pane_l.add_to(m)

custom_pane_r = CustomPane(name='right', z_index=1000, pointer_events=True)
custom_pane_r.add_to(m)

# Create tile layers for the left and right panes
layer_right = folium.TileLayer('openstreetmap', pane='right')
layer_left = folium.TileLayer('cartodbpositron', pane='left')

# Add SideBySideLayers control to compare the two layers
sbs = SideBySideLayers(layer_left=layer_left, layer_right=layer_right)
layer_left.add_to(m)
layer_right.add_to(m)
sbs.add_to(m)

# Add a custom marker on the left pane
marker = folium.Marker([51.5074, -0.1278], popup="This is a custom marker!", pane="left")
marker.add_to(m)

# Example GeoJSON data for the right pane
geojson_data = {
    "type": "FeatureCollection",
    "features": [
        {
            "type": "Feature",
            "geometry": {
                "type": "Polygon",
                "coordinates": [
                    [
                        [-0.1278 - 0.1449, 51.5074 - 0.0898],  # Bottom-left corner
                        [-0.1278 + 0.1449, 51.5074 - 0.0898],  # Bottom-right corner
                        [-0.1278 + 0.1449, 51.5074 + 0.0898],  # Top-right corner
                        [-0.1278 - 0.1449, 51.5074 + 0.0898],  # Top-left corner
                        [-0.1278 - 0.1449, 51.5074 - 0.0898]   # Closing the polygon
                    ]
                ]
            },
            "properties": {
                "name": "London 10km x 10km Square"
            }
        }
    ]
}

# Add the GeoJSON layer to the right pane
geojson_layer = folium.GeoJson(geojson_data, name='GeoJSON Example', pane='right')
geojson_layer.add_to(m)

The marker is correctly in the left pane only, but the polygon is on both panes...

image

@hansthen
Copy link
Collaborator

hansthen commented Nov 9, 2024

Folium is just a thin python wrapper around the javascript Leaflet library (and contributed plugins.) We cannot do bug fixes or feature requests for the upstream packages.

I did some digging, but this is a known issue with the underlying Leaflet plugin.
See: digidem/leaflet-side-by-side#4. There are several comments about this not working with GeoJson. There even is a Pull Request for a fix.

You can override the underlying plugin source and make it point to: https://raw.githubusercontent.com/s22s/leaflet-side-by-side/refs/heads/feature/support-img-overlay-geojson/leaflet-side-by-side.min.js

See the docs for examples: https://python-visualization.github.io/folium/latest/advanced_guide/customize_javascript_and_css.html.

I did not test this myself, so maybe it will not work with GeoJson, but you could try it. If it works, let us know, and we can improve our documentation.

@LukeAFullard
Copy link

Folium is just a thin python wrapper around the javascript Leaflet library (and contributed plugins.) We cannot do bug fixes or feature requests for the upstream packages.

I did some digging, but this is a known issue with the underlying Leaflet plugin. See: digidem/leaflet-side-by-side#4. There are several comments about this not working with GeoJson. There even is a Pull Request for a fix.

You can override the underlying plugin source and make it point to: https://raw.githubusercontent.com/s22s/leaflet-side-by-side/refs/heads/feature/support-img-overlay-geojson/leaflet-side-by-side.min.js

See the docs for examples: https://python-visualization.github.io/folium/latest/advanced_guide/customize_javascript_and_css.html.

I did not test this myself, so maybe it will not work with GeoJson, but you could try it. If it works, let us know, and we can improve our documentation.

Thank you, I will report back

@hansthen
Copy link
Collaborator

@LukeAFullard did you manage to make any progress? Can we close this issue?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants