OpenLayers 3: Comment vérifier si la source vectorielle est prête?

8

ol.source.getState()ne semble pas fiable. Lorsque je l'appelle sur une source vectorielle, il revient prêt, mais les fonctionnalités ne sont pas encore disponibles. Le code ressemble à ceci:

var vectorSource = new ol.source.Vector({
  url: 'world.topo.json',
  format: new ol.format.TopoJSON()
});

// ... init map with vectorSource

console.log(vectorSource.getState()); // returns "ready"
console.log(vectorSource.getFeatureById("US")); // returns null

Une autre façon de voir si une source vectorielle est prête?

johjoh
la source
Avez-vous vérifié si cet ID de fonctionnalité existe?
Jonatas Walker
@JonatasWalker, oui, il existe.
johjoh

Réponses:

8

Vous pouvez fournir votre propre fonction de chargeur et définir des écouteurs personnalisés, comme suit:

var source = new ol.source.Vector({
    loader: function(){
        var url = '....../data/json/world-110m.json';
        var format = new ol.format.TopoJSON();
        var source = this;

        //dispatch your custom event
        this.set('loadstart', Math.random());

        getJson(url, '', function(response){

            if(Object.keys(response).length > 0){
                var features = format.readFeatures(response, {
                    featureProjection: 'EPSG:3857'
                });
                source.addFeatures(features);
                //dispatch your custom event
                source.set('loadend', Math.random());
            }
        });
    }
});

Définissez des écouteurs personnalisés:

//custom source listener
source.set('loadstart', '');
source.set('loadend', '');

source.on('change:loadstart', function(evt){
    console.info('loadstart');
});
source.on('change:loadend', function(evt){
    console.info('loadend');
});

Et une fonction xhr:

var getJson = function(url, data, callback) {

    // Must encode data
    if(data && typeof(data) === 'object') {
        var y = '', e = encodeURIComponent;
        for (x in data) {
            y += '&' + e(x) + '=' + e(data[x]);
        }
        data = y.slice(1);
        url += (/\?/.test(url) ? '&' : '?') + data;
    }

    var xmlHttp = new XMLHttpRequest();
    xmlHttp.open("GET", url, true);
    xmlHttp.setRequestHeader('Accept', 'application/json, text/javascript');
    xmlHttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
    xmlHttp.onreadystatechange = function () {
        if (xmlHttp.readyState != 4){
            return;
        }
        if (xmlHttp.status != 200 && xmlHttp.status != 304){
            callback('');
            return;
        }
        callback(JSON.parse(xmlHttp.response));
    };
    xmlHttp.send(null);
};

Démo de travail .

Jonatas Walker
la source
Ça marche bien! Désolé pour une approbation tardive. Il y a deux ans, je ne l'ai pas vraiment compris et j'ai trouvé ma propre solution - qui n'était pas fiable comme il s'est avéré maintenant.
johjoh
4

Vous pouvez attacher un écouteur à votre vectorSource http://openlayers.org/en/v3.7.0/apidoc/ol.source.Vector.html#once

par exemple

vectorSource.once('change',function(e){
    if (vectorSource.getState() === 'ready') {
        vectorSource.getFeatureById("US");
    }
});
Gars
la source
Oui, c'est ce que je fais déjà, mais l'événement ne se déclenchera pas, si la source était déjà chargée auparavant. Je voulais donc vérifier si la source était prête. Si c'est le cas, travaillez dessus immédiatement - sinon, liez-le à l'événement change.
johjoh
0

Je me suis retrouvé avec la fonction suivante, pour exécuter du code lorsque la source vectorielle est prête:

doWhenVectorSourceReady : function(callback) {
  var map = this;

  if (map.vectorSource.getFeatureById("US")) { // Is this a relieable test?
    callback();
  } else {
    var listener = map.vectorSource.on('change', function(e) {
      if (map.vectorSource.getState() == 'ready') {
        ol.Observable.unByKey(listener);
        callback();
      }
    });
  }
}

Je ne sais pas si le test d'une seule fonctionnalité est fiable, car il se peut que toutes les fonctionnalités ne soient pas disponibles en même temps.

johjoh
la source
Ce n'est pas fiable, comme cela s'est avéré maintenant. Vérifier une fonctionnalité ne dit pas si les autres sont là. Voir la réponse acceptée. Cela fonctionne bien pour moi.
johjoh