Comments (9)
Ah, interesting suggestions. What does "load" mean for you in each of these contexts, and what are your use cases exactly?
from map-gl-utils.
I guess a loaded source means when all features have been set as data and are available, and a loaded layer would mean when has already been drawn on the map.
There are many events in mapbox such as sourcedata
or style.load
that may be used together to verify the resource status, but all implementations I've been using end up being a little bit buggy.
This is the most recent I'm using to detect source changes, still not giving 100% good results
const sourceId = 'source_id';
const sourceLoaded = source => {
console.log('Source loaded', source);
};
const onLoadStart = startEvent => {
if (startEvent.sourceId === sourceId) {
map.off('dataloading', onLoadStart);
const onLoadEnd = () => {
if (endEvent.sourceId === sourceId && endEvent.isSourceLoaded && map.isSourceLoaded(sourceId)) {
map.on('dataloading', onLoadStart);
map.off('sourcedata', onLoadEnd);
sourceLoaded(map.getSource(sourceId));
}
};
map.on('sourcedata', onLoadEnd);
}
};
map.on('dataloading', onLoadStart);
Use cases are multiple, in my case I'm using to detect when a vector tile source has finished to (re)load after a pan or zoom change.
I'm also using styledata
and style layers checks to trigger an event when some layers change in a legend plugin I'm working on, again with some headaches :P
from map-gl-utils.
Yeah, the inability to consistently detect these events is such a huge pain point :/
If you can come up with an implementation you're satisfied with, I'd be happy to include it.
from map-gl-utils.
I'm making some VERY OPINIONATED assumptions and I haven't tested widely so I'm not sure about possible side effects, but seems to work pretty well on my use case and it's clearly a lot more readable that my previous suggestion.
const onSourceLoad = (name, { onLoadStart, onLoadEnd }) => {
let isSourceLoading = false;
map.on('sourcedata', event => {
if (event.sourceId !== name) return;
// Source starts loading
// Consider an "initial" data event when sourceDataType is undefined or `content`
// Discard `visibility` as it triggers very irregularly
const { sourceDataType = 'content' } = event;
if (!isSourceLoading && sourceDataType === 'content') {
if (onStartLoading) onStartLoading(map.getSource(name));
isSourceLoading = true;
}
// Source finishes loading
if (isSourceLoading && map.isSourceLoaded(name)) {
if (onEndLoading) onEndLoading(map.getSource(name));
isSourceLoading = false;
}
});
};
I've changed a little bit the approach to trigger different actions when layer starts and finishes loading, so it could be used as:
map.U.onSourceLoad('sourcename', {
onLoadStart: source => { /* Do whatever */ },
onLoadEnd: source => { /* Do whatever */ },
});
I'm currently using this method to show and hide a loading spinner whenever a vt source is updating.
from map-gl-utils.
Thanks for this - looks useful. I will have to look more closely. I'm a little bit iffy about the function signature (having to spell out onLoadStart
and onLoadEnd
...). Maybe it would be cleaner/simpler to just have two separate functions: map.U.onSourceLoadStart(name, cb)
and map.U.onSourceLoadEnd(name, cb)
.
Does this work on both vector tiles and GeoJSON? Does it trigger per tile, or after all the tiles for the current view have loaded?
from map-gl-utils.
Object signature is convenient in my particular usecase, but certainly adds some bloating.
Works both on vt and geojson. Some considerations:
- Triggers on geojson when zooming and panning, like if load was batched internally. I may have misunderstood how geojson works, but I thought it was loaded at once.
- Triggers on vector tiles once all tiles have finished loading. Sometimes keeps waiting if a tile is partially offscreen and not fully rendered.
I wish Mapbox will release some day a good source and layers events API, because all this starts to feel very hacky to me 😓
from map-gl-utils.
Triggers on geojson when zooming and panning, like if load was batched internally. I may have misunderstood how geojson works, but I thought it was loaded at once.
GeoJSON is loaded in bulk but then converted into vector tiles by mapbox-gl-js.
I have now tested this and it does seem useful.
from map-gl-utils.
I found an edge case. Functions where triggered by sourcedata
on any source/layer change, including setting a simple filter in a layer. I solved it by splitting into two functions and binding the onStartLoading part to the sourcedataloading
event. This seems to work smoother only when actual source data is being loaded.
let isLoading = false;
const bindLoadStart = event => {
const { sourceDataType = 'content' } = event; // Little hack here
if (event.sourceId === sourceId && !isLoading && sourceDataType === 'content') {
if (onStartLoading) onStartLoading(event);
isLoading = true;
}
};
const bindLoadEnd = event => {
if (event.sourceId === sourceId && isLoading && map.isSourceLoaded(sourceId)) {
if (onEndLoading) onEndLoading(event);
isLoading = false;
}
};
const bindLoading = () => {
map.on('sourcedataloading', bindLoadStart);
map.on('sourcedata', bindLoadEnd);
};
const unbindLoading = () => {
map.off('sourcedataloading', bindLoadStart);
map.off('sourcedata', bindLoadEnd);
};
Sorry if I'm spamming too much on this topic. Just wanting to let you know.
from map-gl-utils.
Thanks, this is great.
from map-gl-utils.
Related Issues (20)
- Support regex (and maybe function) as alternative to arrays
- addVector extra props doesn't work
- Return promise from loadImage()
- Add getLineColor etc functions
- Make idempotent add/update layer style functions HOT 2
- Add fontsInUse() HOT 2
- Possibility to use outside node? HOT 4
- Support debug hover over
- Support multi-layer `on`
- setLayerSource cannot be seen in https://stevage.github.io/map-gl-utils/
- Website TOC resize handle broken HOT 3
- Support setMinzoom
- Error with clickPopup on line features
- Next publish? HOT 3
- Updating Vector Source
- License and commercial use HOT 1
- Typescript definitions HOT 1
- Mapbox GL JS v3 Support HOT 3
- make layer type optional in props? HOT 1
- regeneratorRuntime is not defined
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from map-gl-utils.