Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to load data after map style is loaded #2268

Closed
Iam-jegan opened this issue Mar 15, 2016 · 10 comments
Closed

How to load data after map style is loaded #2268

Iam-jegan opened this issue Mar 15, 2016 · 10 comments

Comments

@Iam-jegan
Copy link

mapbox-gl-js version: latest version

getting error like "Style not done loading" often. Can you please tell me how to avoid this?

@mourner
Copy link
Member

mourner commented Mar 15, 2016

Source/layer manipulations can only be done after the style is loaded, so you have to wrap you code in map.on('style.load', function () { ... }) handler. See examples, e.g. this one: https://www.mapbox.com/mapbox-gl-js/example/geojson-layer-in-stack/

@mourner mourner closed this as completed Mar 15, 2016
@shantilal-narola
Copy link

http://fuzzytolerance.info/blog/2016/03/16/Leaflet-to-Mapbox-GL/

Use this, this will defiantly work.

@nathanredblur
Copy link

Even if the that event is triggered, your map could be not full ready.
It's an issue in MapBox, I needed to do this to solve my problem

myMap.on('style.load', () => {
  const waiting = () => {
    if (!myMap.isStyleLoaded()) {
      setTimeout(waiting, 200);
    } else {
      loadMyLayers();
    }
  };
  waiting();
});

@CodeAmend
Copy link

I have been trying to figure out how to do this without a timeout. My issue was the text was not rendering by the time the on load event was called. So instead of using map.on('load'), i would use map.on('idle').

map.on('idle', () => {
   // map.getCanvas().toDataURL()
}

@djibarian
Copy link

Where is the style.load event documented?? Not good having to spend the entire day trying to load stuff on top of the style (the synchronous nature of styleimagemissing is a pain, load event is a waste because you have to wait also for the render, same with idle; and on top of that, there is an issue where in style.load sometimes the style is not ready?).

The timeout hack is error prone by definition. Also, I just learned that if you change the style you lose all the sources, layers, images, etc. you loaded afterwards; and all the solutions to preserve them look also very hacky.

Am I missing something? Or a very common task which is loading stuff on top of a basemap is really hard to do properly?

@ryanhamley
Copy link
Contributor

style.load isn't documented as it was never really intended to be a public API. All of our examples, I believe, use map.on('load', ...); for this reason. I would respectfully disagree that loading layers on to a map is difficult. That's exactly what we created the load and idle events for. We recognize that style.load can be confusing and somewhat inconsistent and we'd like to fix it at some point. That being said, it's not super high priority because load and idle provide reliable, documented workarounds. We do welcome PRs though if anyone is interested in contributing.

As for the need to add layers when switching styles, that's a deliberate choice. GL JS regards the style as the declarative source-of-truth for how a map should be rendered. Adding sources and layers which are not in that style and have not been explicitly added to it breaks that paradigm. It might be possible to add an option to allow the retention of sources and layers when switching to a new style, but I don't think GL JS should make that choice on its own.

If you have a specific use case that you're having trouble getting set up, you can contact Mapbox Support for guidance. Thanks!

@djibarian
Copy link

@ryanhamley Thanks for answering so quickly. What I wrote is the conclusion of my humble experience. I started a few days ago playing with Mapbox and I am delighted about the ease of use and the fantastic documentation. I can feel Leaflet simplicity in most of Mapbox, and coming from OpenLayers everything was heaven so far... until I went into the details.

Then in a single day I was stuck with not one, but a few single basic and common tasks which can’t be solved easily and elegantly, and that confused me because of the nice beginnings.

Don’t get me wrong, I will find ways of doing everything the right way, but in my experience so far is not easy. And that’s the reason you can see people using those hacky solutions that work 95% of the time. I think that’s a problem, because you should think about the most common scenarios and provide good solutions to them.

If Mapbox GL JS is made for performance, why don’t you provide a reliable and documented hook to listen for the style loaded, so you can immediately load your sources and create additional layers while the map is still being rendered? Instead, you have to use load or idle events, which are fired when the last tile is rendered, way long after the style is loaded. Why that wait? Why do you need the map to be rendered up to the last pixel before creating a source or a layer of your own? This is obviously perceived as a performance penalty from a UX perspective, you can easily feel that the map behaves slower. And most of the people will do that, because it’s the documented way.

Maybe there are underlying technical issues I don’t understand, but from my point of view the “basemap” style and the things you put on top of it usually have nothing to do between them. So why you should have to recreate them if you change the “basemap”? Why do you have to wait for the “basemap” to be fully rendered before you are able to create a source or a layer? Probably these questions are very common for beginners, and impose some limitations that have to be well reasoned.

Another example is the styleimagemissing event. Very nice to create images of coloured squares like in the example, but in real life you wouldn’t do that most of the time. You would load assets on demand, asynchronously, which makes the event a little bit difficult to use, because every single developer has to figure out how to handle async loads and repaints in a synchronous event, and most of them won’t come up with the right solution.

In the end I’m only trying to shape my mind to the Mapbox model, which as I said is fantastic in some areas.

(By the way, at least the “Add a 3D model” example is using style.load, and if undocumented, @mourner shouldn’t have advised about using it, I think).

@ryanhamley
Copy link
Contributor

Thanks for the thoughtful reply. I hear you and you bring up a lot of valid points. As I noted previously, we understand the need and desire for a reliable, documented version of style.load. There are underlying technical issues (we're already parsing a style and creating buckets and such) that have to be handled to implement this properly. The issue I linked to talks about lazily loading the sources because of those technical issues. It's certainly not insurmountable but it isn't necessarily a straightforward implementation either. I don't mean to make excuses. We're always working to improve GL JS. However, we're a small team working on a large product with lots of users. There are many competing interests and desires that we have to balance when planning what to work on. While we want to eventually add something like this, we also recognize that there are solid workarounds and for most users, the difference between using style.load and load is generally going to be acceptable. We try to keep discussion centralized in one ticket for any given issue so what I can recommend is adding your use case and thoughts to #10191 so that it doesn't get lost in a closed ticket.

@andrewtuplin
Copy link

andrewtuplin commented May 26, 2023

style.load isn't documented as it was never really intended to be a public API. All of our examples, I believe, use map.on('load', ...); for this reason....

This is certainly not the case now. https://docs.mapbox.com/mapbox-gl-js/example/add-3d-model/ uses style.load.
This one https://docs.mapbox.com/mapbox-gl-js/example/query-terrain-elevation/ uses both map.once('style.load') and await map.once('idle');

Why these options are being used is not well documented.

@mattijsf
Copy link

mattijsf commented Jun 2, 2023

style.load is also mentioned in this example:

https://docs.mapbox.com/mapbox-gl-js/example/style-switch/

For me it is not clear what is the concrete difference between load &style.load:

style.load:

Fired immediately after all style resources have been downloaded and the first visually complete rendering of the base style has occurred.

load:

Fired immediately after all necessary resources have been downloaded and the first visually complete rendering of the map has occurred.

So it's "all style resources" vs "all necessary resources"? I'm still confused, when is which more suitable?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

9 participants