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 do I perform the callback after the GeoJSONSource#setData () setting is complete?? #4904

Closed
jayantchens opened this issue Jun 28, 2017 · 3 comments

Comments

@jayantchens
Copy link

mapbox-gl-js version:0.38

1.I'm getting a route animation,but found a bug...
2.I am passing the requestAnimationFrame to perform the route animation
3.I set a Marker and hope that every time the route is fully drawn successfully, marker # setLngLat () sets the marker latitude and longitude as the last route point, but I find that the time to draw the full route and set the marker latitude and longitude are not synchronized. Route drawing time is slow)

image

@anandthakker
Copy link
Contributor

How do I perform the callback after the GeoJSONSource#setData () setting is complete?

There's some discussion in #3964 about offering promises or callbacks for asynchronous methods, but as of now, it doesn't exist. The best way to know if setData() is complete would be to listen for the sourcedata event and to inspect the MapDataEvent object it emits.

@cyrilchapon
Copy link

cyrilchapon commented Sep 19, 2017

I'm using something like

    var dataLoadedPromise = function(sourceId, waitForSourceLoaded) {
      var deferred = $q.defer();

      var handler = function(e) {
        if(!e.sourceId || e.sourceId !== sourceId) {
          return;
        }

        if(waitForSourceLoaded && !e.isSourceLoaded) {
          return;
        }

        deferred.resolve();
        map.off('sourcedata', handler);
      };

      map.on('sourcedata', handler);

      return deferred.promise;
    };

Which I use like this :

mainPromise.then(function() {
  var dataLoaded = dataLoadedPromise('myLines', true)
  .then(dataLoadedPromise('myPoints', true));

  myFuncThatSetData();

  return dataLoaded;
})

It's ugly, it would deserve any error handling / event unbinding, and I seems to have issues sometimes, though

@anandthakker
Copy link
Contributor

Here is an example of how this can currently be accomplished. Similar to the above by @cyrilchapon (thanks!)

var map = new mapboxgl.Map({
    container: 'map',
    style: 'mapbox://styles/mapbox/streets-v9',
    center: [-73.13734351262877, 45.837451890638886],
    zoom: 5
});
  
var position = [-73.13734351262877, 45.837451890638886];

map.on('load', function () {
    map.addLayer({
        'id': 'dot',
        'type': 'circle',
        'source': {
            'type': 'geojson',
            'data': {
                'type': 'Feature',
                'geometry': {
                    'type': 'Point',
                    'coordinates': position
                }
            }
        },
        'layout': {},
        'paint': {
            'circle-radius': 20,
            'circle-color': 'red'
        }
    });    
  
    animate();
});
 
count = 1000;
function animate() {
  if(--count < 0) return;
  position[0] -= 0.01;
  position[1] -= 0.01;
    
  // listener for sourcedata event.
  function onSourceData (e) {
    if (e.isSourceLoaded) {
      // the update is complete: unsubscribe this listener and
      // move on with whatever we need to do next (in this case,
      // schedule the next step in the animation)
      map.off('sourcedata', onSourceData);
      requestAnimationFrame(animate);
    }
  }
  map.on('sourcedata', onSourceData);
  
  
  map.getSource('dot').setData({
      'type': 'Feature',
      'geometry': {
          'type': 'Point',
          'coordinates': position
      }
  })
}

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

3 participants