Closed diehl closed 1 month ago
Hi @diehl
Yes, this is possible. You can create a custom basemap, see this example for details. At a bare minimum you need to use a background layer:
from maplibre.ipywidget import MapWidget, MapOptions
from maplibre.basemaps import background, construct_basemap_style
m = MapWidget(MapOptions(style=background("yellow")))
Furthermore it is also possible to adjust any given basemap style. This example will change the water color to "yellow":
from maplibre.ipywidget import MapWidget, MapOptions
from maplibre.basemaps import Carto
m = MapWidget(MapOptions(style=Carto.DARK_MATTER_NOLABELS))
m.set_paint_property("water", "fill-color", "yellow")
@crazycapivara Hi Stefan, This is brilliant news!!
Let me add a little more color about what I'm trying to achieve in terms of workflow.
I would love to be able to design a custom map style either with Mapbox Studio or Maputnik and then utilize your library to interleave a data layer into the stack of layers defining the basemap. If this is possible, I'd appreciate pointers on how to load the style and then specify where in the basemap layer stack the data layer should go.
If it is helpful, I'd be more than happy to write up an example with your guidance that could be included in the documentation. This capability coupled with the option to use the library in Shiny applications is of immense value!!
@diehl
I am not sure, why you need to add the data layers to the basemap but you can do it this way:
from maplibre.ipywidget import MapWidget as Map
from maplibre import MapOptions, Layer, LayerType
from maplibre.sources import GeoJSONSource
import requests
# Load style
style = requests.get('https://basemaps.cartocdn.com/gl/dark-matter-nolabels-gl-style/style.json').json()
# Add data source to style
style["sources"]["earthquakes"] = GeoJSONSource(data="https://docs.mapbox.com/mapbox-gl-js/assets/earthquakes.geojson").to_dict()
# Add layer to style using the added source above
earthquakes_layer = Layer(type=LayerType.CIRCLE, id="earthquakes", source="earthquakes", paint={"circle-color": "yellow", "circle-radius": 5})
style["layers"].append(earthquakes_layer.to_dict())
# Use basemap
m = Map(style=style)
If this is a usecase, we can add a function to the package for this.
Hi @crazycapivara,
Let me try to clarify in case my terminology is causing confusion. All the existing Python geospatial visualization libraries that I'm aware of place the data layer(s) on top of the basemap. Therefore one cannot see state/country boundaries, place names, road networks etc. that provide geospatial context. What I'm looking for is the ability to slot the data layer(s) into the stack of layers that comprise the basemap such that state/country boundaries, place names and any other desired geospatial context remains on top and readily visible.
I'm assuming that
style["layers"].append(earthquakes_layer.to_dict())
will result in the earthquake layer being placed on top of all the other layers that define the basemap. If I wanted to insert it such that some layers remain on top, I assume that would be accomplished by adding earthquake_layer
somewhere in the middle of that list. Is that correct?
Please let me know if that helps clarify the use case. Thank you again!
@diehl
Ah, ok, yes you are right, you just need to insert it somewhere in the middle.
But then for your use case, it might be easier if I add the before_id
parameter in the add_layer
function:
https://maplibre.org/maplibre-gl-js/docs/API/classes/Map/#addlayer
I just forgot to add the param, when implenting the binding function.
See also Example in JS.
@crazycapivara
Boom. That's exactly what is needed here. If you could add the before_id
parameter into the mix, that would be brilliant!
@diehl
This PR adds the needed parameter, just tested it, maybe you have a nice example that I can add to the docs.
Awesome @crazycapivara!
I've got an idea for a map. Can I get your email so we can discuss a possibility? Happy to help craft something.
Just added an example based on the JS example above. @diehl feel free to add another example via PR or issue. Thanks for the great input.
My pleasure @crazycapivara - thank you!
Is it possible to use this library to interleave a data layer into the basemap such that place names and administrative boundaries at a minimum remain on top? To date, I've not found a Python-based solution to generating this type of visualization. Data layers always appear on top of the basemap, occluding the geospatial context, leaving one to resort to transparency as the only option for exposing the geospatial context below the data layer.