3

I'm adding a vector tile source to my Mapbox GL js map like this:

    this.map.on('load', () => {
        this.map.addSource('userSource', {
            type: 'vector',
            url: 'mapbox://<my user source>',
        });

        this.map.addLayer({
            id: 'userDataLayer',
            type: 'fill',
            source: 'userSource',
            'source-layer': 'foobar_areas',
            paint: {
                'fill-outline-color': 'rgba(50,50,150,.4)',
                'fill-color': 'rgba(10,190,20,.2)',
            },
        });
    });

I want to initialize some other modules once userDataLayer is ready to go, but I don't know what event to listen for. I tried this:

this.map.on('data', (e) => { 
    const { dataType, sourceId, isSourceLoaded } = e; 
        if (dataType === 'source' && sourceId === 'userSource' && isSourceLoaded) {
        // ...

Except that fires many times... and then fires again when you apply filters, etc.

Is there an event that fires just when the source is loaded?

6

I was dealing with this again today, so here's an update!

As of mapbox-gl v0.44.2, it's still not quite reliable enough to listen for the sourcedata event and check the properties of the event parameter that gets passed to the callback, even though I think that's what you're supposed to do. You'd want to check sourceId === 'your-source-id', isSourceLoaded === true, and sourceDataType !== 'metadata'. If an event satisfied these 3 things, you could assume your source is loaded and ready to work with.

I've been experimenting with this technique, and I found that switching the source at runtime doesn't always fire a sourcedata event that satisfies these criteria. It's a real hassle.

The most solid solution I've been able to find so far is to listen for sourcedata events, but use map.isSourceLoaded every single time to check if your particular source is ready.

So:

function sourceCallback() {
    // assuming 'map' is defined globally, or you can use 'this'
    if (map.getSource('my-data') && map.isSourceLoaded('my-data')) {
        console.log('source loaded!');
    }
}

map.on('sourcedata', sourceCallback);
2

The solution is to use the undocumented style.load event that fires when new things finish loading into the style.

map.once('style.load', (ev) => {
    // ...
});
  • i wonder why this event is not documented ?!! – Ibrahim Mohammed Mar 1 '18 at 12:05
  • I know that using the undocumented style.load event is discouraged, so I've added a new answer that is hopefully less hack-ish. I really hope future versions of mapbox-gl simplify things with promises or async methods! – DMack May 7 '18 at 23:22
1

You can use below line of code

map.on('idle',function(){
   //your code here 
})

Once all the rendering part has been done then the above function will be called and then you can perform other operations.

For reference, you can follow the link : Mapbox Documentation Link

  • I haven't tried that yet because it was just added in v0.52.0, but that sounds very promising! – DMack Mar 7 at 0:45
0

The answer in 2019 is:

map.once('styledata', loadTiles); //The listener will be called first time the event fires after the listener is registered.

      map.once('styledata', loadTiles);   //The listener will be called first time the event fires after the listener is registered.


     map.on("styledata", loadTiles);    // will fire multiple 3 times, whenever style changed.  
                                // event.stopPropagation(); does not work.


     map.on("load", loadTiles);       // only fire 1 time. but when you change base map, use below

  map.setStyle('mapbox://styles/mapbox/' + layerId, {diff: false});

    //  on load event will not fire, which I need it fire to re-load geojson layer. 


       map.on("styledata"    // works fine, but it fire 3 same event at same time, cause load 3 times geojson layer, cause other error when you load 3 times geojson layer at same time.
  • styledata fires any time the style loads or changes, so you can't guarantee that your style will be loaded when this fires. It's much safer to use load or the idle event depending on your situation. – DMack Oct 4 at 22:45
  • that is why I use 'map.once' above, if you use map.on, you will get 3 continues same event, which I do not want to. So I use 'once' will only get 1 event, every register. That means, if you want to get that fired next time, you have to register it again, and get another event fired. So use 'once' will prevent you get multiple event. – hoogw Oct 7 at 15:26

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.