2016-07-07 3 views
5

Я работаю над проектом с использованием OL3, в котором мне нужно иметь возможность вручную (путем нажатия кнопки) или автоматически (по времени) перезагрузить векторные слои, если они были обновлены с момента последнего загрузки используя HTTP условные GET (304 заголовка и т. д.).OpenLayers 3 Reload Layer (s)

Я нашел это очень старое сообщение (https://gis.stackexchange.com/questions/333/how-to-dynamically-refresh-reload-a-kml-layer-in-openlayers) для слоев KML, но он, похоже, использует переменные, которые больше не найдены в OL3, и я не уверен, что он позволит только загружать файлы, которые были изменены с момента последнего загрузки. На первый взгляд кажется, что полная перезагрузка принудительно, даже если файл не был изменен.

В API нет ничего, что бы напоминало функцию перезагрузки для объектов карты или слоя в OL3. Есть ли способ сделать это?

Update 1:

Я нашел возможный способ сделать это в качестве ответа на этот вопрос: https://gis.stackexchange.com/questions/125074/openlayers3-how-to-reload-a-layer-from-geoserver-when-underlying-data-change используя код:

layer.getSource().updateParams({"time": Date.now()}); 

Однако, когда я запускаю этот код, я получаю ошибку :

При проверке API Reference для OL3, похоже, что таких функций не существует. Ближайшим является setProperties() или setAttributions(). Ни один из них не работает. Также кажется, что не все типы слоев реализуют getSource().

Update 2:

Обновление экрана() перегружает плитки, но не по всей видимости, запрашивающим их с сервера. Скорее, похоже, что они загружаются из кеша (но не кеша HTTP). Запросов не поступает, нет HTTP 304 или что-то в этом роде. Будет пытаться вариант подхода KML и опубликовать результаты в ближайшее время.

Update 3:

После попытки МНОГО различных решений, я случайно наткнулся на то, что работал для векторных слоев. Вызывая функцию source.clear() слоя, а затем вызывая Map.updateSize(), этот слой автоматически перезагружается из исходного URL-адреса. Выдается запрос XHR GET, и если исходный файл изменился, он будет перезагружен из файла. Если исходный файл не изменился, будет выдан 304, и источник будет перезагружен из кеша.

Ниже приводится функция, которая должна использует этот метод, чтобы перезагрузить данный слой:

function refreshLayer(selectedLayer) 
{ 
    var selectedLayerSource = selectedLayer.getSource(); 

    if(selectedLayerSource instanceof ol.source.Vector) 
    { 
     //do vector reload 
     selectedLayerSource.clear(); 
     map.updateSize(); 
    } 
    else 
    { 
     //reload the entire page 
     window.location.reload(); 
    } 
} 

Однако, оказывается, что на первых нескольких попыток (в зависимости от браузера) направляется запрос, 200-код отправляется обратно, но слой не отражает никаких изменений. После нескольких попыток (и перезагрузки страницы несколько раз) это работает. Когда он начинает работать для слоя, он продолжает работать так же часто, как исходный файл изменяется. Кто-нибудь знает, что происходит?

Update 4:

Используя приспособление ответа Jonatas' я получаю лучшие результаты. Новые функции появляются мгновенно при перезагрузке. Однако старые функции не удаляются с карты, и многие функции, которые перемещают местоположения, отображаются на карте дважды.Ниже приведен мой код:

function refreshSelectedLayer() 
{ 
    console.log("This feature is still in the process of being implemented. Refresh may not actually occur."); 

    var selectedLayerSource = selectedLayer.getSource(); 

    if(selectedLayerSource instanceof ol.source.Vector) 
    { 
     var now = Date.now(); 
     var format = selectedLayerSource.getFormat(); 
     var url = selectedLayerSource.getUrl(); 
     url = url + '?t=' + now; 

     loader = ol.featureloader.xhr(url, format); 

     selectedLayerSource.clear(); 
     loader.call(selectedLayerSource, [], 1, 'EPSG:3857'); 

     map.updateSize(); 
    } 
    else if(selectedLayerSource instanceof ol.source.Tile) 
    { 
     selectedLayerSource.changed(); 
     selectedLayerSource.refresh(); 
    } 
} 

Обратите внимание, что var selectedLayer задан в другом месте кода. Любые идеи, почему эти очень странные результаты происходят?

Update 5:

Я заметил, что если я удалю все другие символы кроме:

source.clear(); 

вызова запрос GET XHR сделан и особенности не исчезают. Почему очистка источника не устраняет все функции?

Обновление 6:

После обнаружения, что ol.source.clear() не был на самом деле удаления функции из заданного источника данных/слоя я заменил его, используя следующий код:

selectedLayerSource.forEachFeature(function(feature){ 
     selectedLayerSource.removeFeature(feature); 
    }); 

Вывод функций в слое до и после каждого шага я получил:

var now = Date.now(); 
    var format = selectedLayerSource.getFormat(); 
    var url = selectedLayerSource.getUrl(); 
    url = url + '?t=' + now; 

    console.log("time: "+now+" format: "+format+" url: "+url); 

    loader = ol.featureloader.xhr(url, format); 

    console.log(selectedLayerSource.getFeatures()); 
    console.log("Deleting features..."); 

    /* 
     Try adding code here to manually remove all features from source 
    */ 
    selectedLayerSource.forEachFeature(function(feature){ 
     selectedLayerSource.removeFeature(feature); 
    }); 

    console.log(selectedLayerSource.getFeatures()); 

    console.log("Loading features from file..."); 

    loader.call(selectedLayerSource, [], 1, 'EPSG:3857'); 

    window.setTimeout(function(){ 
     console.log(selectedLayerSource.getFeatures()); 
     map.updateSize(); 
    }, 500); 

Какие выходы в консоль:

"time: 1471462410554 format: [object Object] url: http://server/file.ext?t=1471462410554" file.php:484:3 
Array [ Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, 1 more… ] file.php:491:3 
Deleting features... file.php:492:3 
Array [ ] file.php:501:3 
Loading features from file... file.php:503:3 
GET XHR http://server/file.ext [HTTP/1.1 200 OK 34ms] 
Array [ Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, 1 more… ] 

После нескольких испытаний слоями GeoJSON и KML я подтвердил, что этот метод работает !!!

Однако, поскольку загрузчик выполняет асинхронный запрос, у меня остается проблема с выполнением кода после вызова функции загрузчика. Очевидно, что использование setTimeout() - это ужасный способ сделать это и был реализован только для целей тестирования. Функция обратного вызова успеха/отказа была бы идеальной, и, глядя на источник featureloader.js, кажется, что они предлагаются в качестве параметров в файле ol.featureloader.loadFhaturesXhr. Ниже блока кода от featureloader.js:

/** 
* @param {string|ol.FeatureUrlFunction} url Feature URL service. 
* @param {ol.format.Feature} format Feature format. 
* @param {function(this:ol.VectorTile, Array.<ol.Feature>, ol.proj.Projection)|function(this:ol.source.Vector, Array.<ol.Feature>)} success 
*  Function called with the loaded features and optionally with the data 
*  projection. Called with the vector tile or source as `this`. 
* @param {function(this:ol.VectorTile)|function(this:ol.source.Vector)} failure 
*  Function called when loading failed. Called with the vector tile or 
*  source as `this`. 
* @return {ol.FeatureLoader} The feature loader. 
*/ 
ol.featureloader.loadFeaturesXhr = function(url, format, success, failure) 

Я попытался реализовать эти функции как и при создании погрузчика:

loader = ol.featureloader.xhr(url, format, 
     function(){ 
      console.log(selectedLayerSource.getFeatures()); 
      map.updateSize(); 
      console.log("Successful load!"); 
     }, 
     function(){ 
      console.log("Could not load "+selectedLayerName+" layer data from "+url); 
     } 
    ); 

но ни функция вызывается. Какие-либо предложения? Я чувствую, что я что-то действительно просто здесь не хватает ...

Update 7:

Используя решение, предоставляемое @Jonatas Walker Я приспособил его использовать JQuery:

 var now = Date.now(); 
     var format = selectedLayerSource.getFormat(); 
     var url = selectedLayerSource.getUrl(); 
     url = url + '?t=' + now; 

     //make AJAX request to source url 
     $.ajax({url: url, success: function(result){ 

      //manually remove features from the source 
      selectedLayerSource.forEachFeature(function(feature){ 
       selectedLayerSource.removeFeature(feature); 
      }); 

      //create features from AJAX results 
      var features = format.readFeatures(result, { 
       featureProjection: 'EPSG:3857' 
      }); 

      //add features to the source 
      selectedLayerSource.addFeatures(features); 

     }, 
     error: function(err){ 
      alert("Could not load features from "+selectedLayerName+" at "+url+" error code: "+err.status); 
     } 
     }); 

После обширной тестирование с использованием источников GeoJSON и KML оказалось чрезвычайно надежным методом обновления!

+0

Он существует для _some_ sourcetypes: [TileWMS] (http://openlayers.org/en/latest/apidoc/ol.source.TileWMS.html#updateParams). – peter

+0

А, я вижу! Есть ли у вас какое-либо представление о решении, которое будет работать для всех типов источников? Похоже, что это будет довольно простая функция, которая должна быть встроена в объект layer. – user2395126

+0

Я думаю, что KML-решение, на которое вы ссылаетесь, все еще может работать. Вы смотрите на карту и слои, вы должны смотреть на источники. Многие (все?) Ol sourcetypes имеют упомянутый здесь метод refresh(). – peter

ответ

1

Ну, есть еще один вариант! Имейте свой собственный загрузчик.

Загрузите этот скрипт - только в случае, если кто-то еще использует старые браузеры

<script src="//cdn.polyfill.io/v2/polyfill.min.js?features=fetch"></script> 

Затем загрузите файл в формате JSON и знаю, когда он готов/загружены:

function refreshSelectedLayer(layer) { 

    var now = Date.now(); 
    var source = layer.getSource(); 
    var format = new ol.format.GeoJSON(); 
    var url = '//your_server.net/tmp/points.json?t=' + now; 


    fetch(url) 
    .then(function(response) { 
     return response.json(); 
    }).then(function(json) { 
     console.log('parsed json', json); 

     source.clear(); // if this is not enough try yours 

     var features = format.readFeatures(json, { 
     featureProjection: 'EPSG:3857' 
     }); 
     source.addFeatures(features); 

    }).catch(function(ex) { 
     console.log('parsing failed', ex); 
    }); 
} 
2

Попробуйте адаптацию этого:

function refreshSource() { 
    var now = Date.now(); 
    var source = vectorLayer.getSource(); 
    var format = new ol.format.GeoJSON(); 
    var url = '//your_server.net/tmp/points.json?t=' + now; 
    var loader = ol.featureloader.xhr(url, format); 

    source.clear(); 
    loader.call(source, [], 1, 'EPSG:3857'); 
} 

Хитрость заключается в том, чтобы сообщить браузеру, что это новая нагрузка, изменив URL.

+0

Лучшее решение! Он работает с перерывами. Я заметил, что после обновления KML-файла (добавления или удаления функций) он будет загружать новые функции каждый раз, однако он не удалит функции, которые были удалены из файла KML. Даже после обновления всей страницы эти функции остаются позади. Он перезагружает страницу несколько раз в течение 5-10 минут, прежде чем они исчезнут. Есть идеи? – user2395126

+0

Кроме того, всякий раз, когда я меняю имя функции, это изменение появляется сразу же, если я добавил имя. Если я верну свое имя в исходное состояние и попытаюсь перезагрузить, это изменение не будет поднято, если я не перезагружу всю страницу. – user2395126

+0

Возможно, вы знаете, как реализовать дополнительные параметры отказа успеха для загрузчика функций? – user2395126

Смежные вопросы