maplibre / maplibre-gl-js

MapLibre GL JS - Interactive vector tile maps in the browser
https://maplibre.org/maplibre-gl-js/docs/
Other
6.7k stars 717 forks source link

map.SetStyle(...) conflicts with custom render layers #2587

Open measuredweighed opened 1 year ago

measuredweighed commented 1 year ago

maplibre-gl-js version: 3.0

browser: Safari, Chrome (likely all)

Steps to Trigger Behavior

  1. Set a custom style using map.setStyle(...)
  2. Add a custom render layer like so: maplibre.on("style.load", () => { maplibre.addLayer(customLayer); });
  3. Change the map style using map.setStyle(...) again

Link to Demonstration

This behaviour can be seen live on https://planefinder.net. Tap the settings icon in the top right and toggle Map Appearance in the sidebar that appears (switching between "Road" and "Satellite"). Notice that the yellow aircraft marker layer is hidden by the appearance of the new style.

Expected Behavior

We'd expect the style to switch without impacting our custom render layer.

Actual Behavior

The custom render layer appears to be overlapped by the layers loaded from the new style. This approach has previously worked for MapLibre versions < 3.0 (and before that, Mapbox). I've attached a video showcasing the issue.

https://github.com/maplibre/maplibre-gl-js/assets/1234600/7ea68d7d-2a22-4f44-b7ae-9eb16396dd0c

Addendum

Thank you for such a wonderful 3.0 release. It's wonderful to see the MapLibre project thriving. You've all done incredible work.

eis-ioki commented 6 months ago

@jessegpierce yes, I'll take a look!

@leoleonsio When changing the style maplibre-gl removes all existing layers and adds the layers from the new style. What I have described is a way to keep certain layers that I might have added in addition to the layers from the initial style. So I am not copying any layers, I am merely making sure, that they are not removed.

UberMouse commented 6 months ago

If you do an incremental style update (ie setStyle(newStyle, { diff: true )}) ML does not clobber the custom render layers that have been added, that only happens for a full style rebuild (ie when doing a non-incremental update or when the incremental update fails and it fallsback to a non-incremental). Just an FYI as I don't think anyone else has mentioned this.

eis-ioki commented 6 months ago

@UberMouse I was not able to get the incremental style update to work. Can you provide an example where this works?

@jessegpierce here is the gist where I made those changes: https://gist.github.com/eis-ioki/81d7a02cc00d9ecb2c949d101841ef81/revisions

jessegpierce commented 6 months ago

@eis-ioki, many thanks for the implementation! One question that perhaps doesn't belong here: shouldn't I be able to replace "STREETS" with my custom map ID, e.g. "e8a7d286-0cf1-4165-bac7-7b1854bb30a0", and it work just the same? I get Uncaught TypeError: Cannot read properties of undefined (reading 'id') at the below line:

if (this._options.initialBasemap.id === layerId) {

tarwin commented 6 months ago

Thanks for all the info. I followed the discussion here and managed to get style switching working, while keeping all my custom data / layers.

I managed to do this in the most silly way possible though, by simply re-rendering all custom layers after style.load happens.

Looking forward to a better solution at some point. As always thank you all for your amazing work on MapLibre.

jessegpierce commented 6 months ago

@eis-ioki, many thanks for the implementation! One question that perhaps doesn't belong here: shouldn't I be able to replace "STREETS" with my custom map ID, e.g. "e8a7d286-0cf1-4165-bac7-7b1854bb30a0", and it work just the same? I get Uncaught TypeError: Cannot read properties of undefined (reading 'id') at the below line:

if (this._options.initialBasemap.id === layerId) {

@eis-ioki I noticed the last line of your previous comment: 'Any source and layer that starts with MyCustomPrefix will still be in the new style without reloading.' and in my case I just made "my" as MyCustomPrefix. I added "my" to my custom map ID so it's now "mye8a7d286-0cf1-4165-bac7-7b1854bb30a0" but the map loads STREETS when the image is clicked. Any thoughts?

eis-ioki commented 6 months ago

@jessegpierce There is a working example right here: https://gist.github.com/eis-ioki/81d7a02cc00d9ecb2c949d101841ef81/revisions#diff-189d4566de47fcb47c6a250a22464c8dc36a2b0faf00dbff06b5b15d10973a7aR125-R150

Throw in a debugger into the transformStyle function to see what layers are available in which style and figure out which ones you need. I don't think I can help you any further.