walkerke / mapgl

R interface to Mapbox GL JS v3 and Maplibre GL JS
https://walker-data.com/mapgl
Other
67 stars 2 forks source link

Allow layering of basemaps and setting of z-indices (if possible with maplibre/mapbox gl js) #7

Open kmcd39 opened 1 month ago

kmcd39 commented 1 month ago

Hi!

I'm making plans to switch from leaflet to either deck.gl or maplibre gl js for a lot of my interactive mapping / shiny development work.

Using R/leaflet, I made a practice of initializing maps with different layers: one w/o labels and another with labels separate, and I put the data between them by setting z-indices.

For example, in leaflet, I had:

leaflet() %>%
    addMapPane("tileLabels", # place name labels
               zIndex = 599) %>%
    addProviderTiles(providers$CartoDB.PositronNoLabels) %>%
    addProviderTiles(providers$CartoDB.PositronOnlyLabels,
                     group = 'Place names',
                     options =
                       providerTileOptions(
                         pane = "tileLabels",
                       )) 

And then I could also add map panes for the data with a z-index between the NoLabel layer and the OnlyLabel layer, and give user ability to toggle labels on/off, and have labels appear above the data by default.

I don't see a way to layer provider tiles or basemaps in any R interface to maplibre or other gl js packages, like mapbox or deck.gl. If it's possible, i'd love to see features to layer basemaps and set z-indices using mapgl!!!!

Thank you! I use many of your packages quite frequently.

walkerke commented 1 month ago

Thanks for the note! This is actually natively supported in Mapbox / Maplibre - I'll need to make a few edits to expose it. I'll work up an example to show how!

RWParsons commented 1 month ago

Hi @walkerke,

I'd be really keen to see an example here showing that it's possible to show a map with the polygon layer above the base tiles but have the place labels and road networks above the polygon layer. I've seen it looks possible with mapbox (links below) but I'm not familiar enough with it to implement it within my shiny app.

https://stackoverflow.com/questions/42753217/mapbox-gl-js-display-map-labels-above-layer https://docs.mapbox.com/mapbox-gl-js/example/geojson-layer-in-stack/

Thanks for your work on this package - I really look forward to being able to move my current shiny app (currently leaflet/leafgl) to using mapgl!

walkerke commented 1 month ago

This is now implemented! If you are using Mapbox's new Standard style, there is a slot argument that makes this easier. If you are using MapLibre or one of the other styles, you'll need to use the new before_id argument that tells the mapping engine which layer to put your layer "before" in the stack. The name of this layer may vary from style to style. I use Mapbox Studio to look this up for Mapbox styles; I need to look into how to do this for Carto and MapTiler.

Here's how it works:

A regular map with data on top of everything (default behavior):

library(tigris)
library(mapgl)
options(tigris_use_cache = TRUE)

dallas <- tracts("TX", "Dallas", cb = TRUE)

# Above labels (default)
mapboxgl(mapbox_style("streets")) |> 
  fit_bounds(dallas) |> 
  add_fill_layer(
    id = "dallas",
    source = dallas,
    fill_color = "green",
    fill_opacity = 0.5
  )
image

Below place labels, above road networks:

# Below labels with `before_id`: 
mapboxgl(mapbox_style("streets")) |> 
  fit_bounds(dallas) |> 
  add_fill_layer(
    id = "dallas",
    source = dallas,
    fill_color = "green",
    fill_opacity = 0.5,
    before_id = "building-entrance"
  )
image

Below road networks as well:

# Below roads as well: 
mapboxgl(mapbox_style("streets")) |> 
  fit_bounds(dallas) |> 
  add_fill_layer(
    id = "dallas",
    source = dallas,
    fill_color = "green",
    fill_opacity = 0.5,
    before_id = "tunnel-path"
  )
image

I'll leave this issue open for now as I don't have an options to do the labels toggle you described yet; this is possible in Shiny with set_config_property() but I'll try to handle it alongside #5 as well.