python-visualization / folium

Python Data. Leaflet.js Maps.
https://python-visualization.github.io/folium/
MIT License
6.92k stars 2.23k forks source link

Support xyzservices.TileProvider as an input of tiles #1497

Closed martinfleis closed 2 years ago

martinfleis commented 3 years ago

Is your feature request related to a problem? Please describe.

With the @geopandas team, we have built a new package called xyzservices to serve as a unified place for XYZ tile management. The idea behind this is that other packages will depend on that instead of having their own system and list of supported tiles hard-coded. It would be great to have folium on board with the idea, by supporting xyzservices.TileProvider as an input of tiles.

xyzservices itself does not have any dependencies which makes it a non-problematic dependency.

It is worth mentioning that xyzservices stores providers' metadata in JSON under share, accessible for anyone if you have a use case for that.

I am happy to do any changes in xyzservices needed to make it as useful for you as possible if that allows centralising maintenance of providers in one place.

Describe the solution you'd like

I'd like to see the support of TileProvider as an input of tiles and TileLayer.

import xyzservices.providers as xyz

m = folium.Map(
    location=[53.4108, -2.9358],
    tiles=xyz.CartoDB.Positron,
)
folium.TileLayer(tiles=xyz.CartoDB.Positron).add_to(m)

All the info TileLayer require can be fetched from the TileProvider object under the hood.

Describe alternatives you've considered

You can pass individual attributes manually as we currently do in xyzservices docs but it can be streamlined with a built-in support.

tiles = xyz.CartoDB.Positron

folium.Map(
    location=[53.4108, -2.9358],
    tiles=tiles.build_url(scale_factor="@2x"),
    attr=tiles.html_attribution,
)

Additional context

Support of xyzservices is being implemented across the ecosystem, from geopandas' own packages (new built-in foilum-based plotting (https://github.com/geopandas/geopandas/pull/1953) and contextily) to leafmap (https://github.com/giswqs/leafmap/issues/91), ipyleaflet (https://github.com/jupyter-widgets/ipyleaflet/issues/854) and holoviews (https://github.com/holoviz/holoviews/issues/5057) (+ hopefully more).

If there's anything we would need to implement in xyzservices to make all this work, I am all ears.

Implementation

I am happy to contribute this as a PR.

In this case, it is actually quite simple and can be done without importing xyzservices as TileProvider is a subclass of dict. Something along this:

if isinstance(tiles, dict):
     attr = attr if attr else tiles.html_attribution
     min_zoom = tiles.get("min_zoom", 0)
     max_zoom = tiles.get("max_zoom", 18)
     tiles = tiles.build_url()
ocefpaf commented 3 years ago

I am happy to contribute this as a PR.

I've been planning to open this issue since you announced xyzservices on Twitter :-)

If you have the time for the PR please do send it in our way! It will be an awesome addition to folium.

Insighttful commented 1 year ago

I came here to see if folium supported xyzservices - and it now does. Thank you.