我发现这个非常古老的帖子(https://gis.stackexchange.com/questions/333/how-to-dynamically-refresh-reload-a-kml-layer-in-openlayers)用于KML图层,但它似乎使用了在OL3中找不到的变量,我不确定它是否只允许加载自上次加载以来已修改过的文件.乍一看,即使文件尚未修改,也会强制执行完全重新加载.
API中似乎没有任何类似于OL3中的地图或图层对象的重新加载功能.有没有办法做到这一点?
更新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()});
TypeError: selectedLayer.getSource(...).updateParams is not a function
在检查OL3的API参考时,似乎不存在这样的功能.最接近的是setProperties()或setAttributions().两者都不奏效.似乎并非所有图层类型都实现了getSource().
更新2:
refresh()重新加载磁贴,但似乎没有从服务器请求它们.相反,它似乎是从缓存(但不是HTTP缓存)加载.没有请求,没有HTTP 304或类似的东西.将尝试使用KML方法的变体并尽快发布结果.
更新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代码,但该层不反映任何更改.经过几次尝试(并重新加载页面几次),它可以工作.一旦它开始为图层工作,它就会在源文件发生变化时继续工作.有谁知道发生了什么事?
更新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在代码中的其他位置设置.有什么想法为什么会出现这些非常奇怪的结果?
更新5:
我注意到如果我除了以下所有其他代码:
source.clear();
调用XHR GET请求并且功能不会消失.为什么清除源不删除所有功能?
更新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,'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,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,1 more… ]
在使用GeoJSON和KML图层进行多次测试后,我确认此方法有效!
但是,因为加载器以异步方式发出请求,所以在调用loader函数之后我遇到了如何执行代码的问题.显然使用setTimeout()是一种可怕的方法,只是为了测试目的而实现的.成功/失败回调函数是完美的,当查看featureloader.js的来源时,它们似乎作为ol.featureloader.loadFeaturesXhr中的参数提供.请参阅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,function(){ console.log(selectedLayerSource.getFeatures()); map.updateSize(); console.log("Successful load!"); },function(){ console.log("Could not load "+selectedLayerName+" layer data from "+url); } );
但这两种功能都没有被调用.有什么建议?我觉得我错过了一些非常简单的东西……
更新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源的广泛测试,这已被证明是一种非常可靠的刷新方法!
解决方法
加载此脚本 – 以防有人仍使用旧版浏览器
<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); }); }