Mapbox-GL setStyle removes layers
Asked Answered
G

3

39

I'm building a mapping web application using Mapbox-GL. It has a lot of cool features. I've set up the buttons to switch base maps (ie. satellite, terrain, etc) following the example on the Mapbox website.

The problem that I am having is that when I change the style it removes my polygons that are loaded as layers and reloads the map. I load in polygons from a Mongo database as layers based on user queries. I want to be able to change the base map and keep those layers.

Is there a way to change the style without reloading the map, or at least not droping the layers?

Here is my code for the switcher, its the same as the example but I added a condition for a custom style:

 var layerList = document.getElementById('menu');
    var inputs = layerList.getElementsByTagName('input');

    function switchLayer(layer) {
        var layerId = layer.target.id;
        if (layerId === 'outdoors') {
            map.setStyle('/outdoors-v8.json');
        } else {
        map.setStyle('mapbox://styles/mapbox/' + layerId + '-v8');
        }
    }

    for (var i = 0; i < inputs.length; i++) {
        inputs[i].onclick = switchLayer;
    }
Gean answered 23/3, 2016 at 2:15 Comment(0)
M
31

Here's an example demonstrating that: http://bl.ocks.org/tristen/0c0ed34e210a04e89984

Unlike a mapping library like Leaftlet, Mapbox GL JS doesn't have a concept of "basemap" vs "other layers." All layers are part of the same entity: the style. So you need to keep some state of the data layer around and call its source/addLayer on each change.

Magulac answered 23/3, 2016 at 3:49 Comment(6)
Awesome! Thanks for the help @tristen. I was hoping that you could just swap the basemap, but Mapbox-GL is a bit different. I used your example for inspiration. Basically I had to save my loaded data to a variable and reload it using the map.on('style.load' ... function. It works pretty well.Gean
Thank you @Magulac for the example and explanation.Smallwood
Thanks @tristen. Any tips on how to do this for vector tiles coming from a tiling server (e.g. localhost/{z}/{x}/{y}.pbf)? geojson can be stored in a variable but if you have a lot of data and only want to show the current bounding box's vector tiles, I'm unsure how to persist the same data...Bradytelic
@Bradytelic sounds like a different question? See mapbox.com/mapbox-gl-js/example/third-party for adding third party vector data to a map. The only thing this example demonstrates is swapping the base layer using setStyle.Magulac
@paolov the token under mapboxgl.accessToken has been disposed. The example should work by copying the code and providing your own access token!Magulac
What's confusing is map.getSource(sourceId) still returns true after a style switchGreening
E
9

Maybe I am late, but just for the record:

  • style.load is not part of the public API
  • use map.on('styledata') to monitor the style change

Please reference:

Eustace answered 3/3, 2020 at 20:25 Comment(2)
this is the correct answer for anyone here in 2020.Marginal
However, 'styledata' will fire multiple times, while 'style.load' only fires once. Yes, it isn't desirable to use a non-public feature, but it works (for now) in cases where the desired behavior is a single firing.Catling
G
1

Other answers suggest that map.on('styledata') is the correct approach. But it doesn't fire reliably, and the related isStyleLoaded is inaccurate.

Looks like we're stuck using style.load for now.

Genvieve answered 31/3, 2021 at 15:6 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.