微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

javascript – OpenLayers 3重新加载图层

我正在使用OL3开发一个项目,我需要能够手动(通过按下按钮)或自动(基于时间)重新加载矢量图层,因为它们自上次加载以来已使用HTTP条件GET(304标题等)进行了更新.

我发现这个非常古老的帖子(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);
    });
}

原文地址:https://www.jb51.cc/js/158024.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐