在OpenLayers中刷新/重绘图层(KML)网络链接自动刷新

5

简述:我希望能够通过定时器刷新图层,以便绘制新的kml数据(类似于更新链接/网络链接)。


到目前为止,我尝试了以下操作函数:

                function RefreshKMLData(layer) {
                    layer.loaded = false;
                    layer.setVisibility(true);
                    layer.redraw({ force: true });
                }

设置函数的时间间隔:

                window.setInterval(RefreshKMLData, 5000, KMLLAYER);

图层本身:

           var KMLLAYER = new OpenLayers.Layer.Vector("MYKMLLAYER", {
               projection: new OpenLayers.Projection("EPSG:4326"),
               strategies: [new OpenLayers.Strategy.Fixed()],
               protocol: new OpenLayers.Protocol.HTTP({
                   url: MYKMLURL,
                   format: new OpenLayers.Format.KML({
                       extractStyles: true,
                       extractAttributes: true
                   })
               })
           });

带有Math随机数的KMLLAYER URL,以避免缓存:

var MYKMLURL = var currentanchorpositionurl = 'http://' + host + '/data?_salt=' + Math.random();

我本以为这会刷新图层。因为将其加载设置为false会卸载它。将可见性设置为true会重新加载它,并且使用Math.random应该不允许缓存。那么有人之前做过这个吗,或者知道我如何使其工作吗?

2个回答

11

考虑到对我来说在这方面很难找到信息,所以我想添加以下内容:


1)

创建KML图层:

            //Defiine your KML layer//
            var MyKmlLayer= new OpenLayers.Layer.Vector("This Is My KML Layer", {
                //Set your projection and strategies//
                projection: new OpenLayers.Projection("EPSG:4326"),
                strategies: [new OpenLayers.Strategy.Fixed()],
                //set the protocol with a url//
                protocol: new OpenLayers.Protocol.HTTP({
                    //set the url to your variable//
                    url: mykmlurl,
                    //format this layer as KML//
                    format: new OpenLayers.Format.KML({
                        //maxDepth is how deep it will follow network links//
                        maxDepth: 1,
                        //extract styles from the KML Layer//
                        extractStyles: true,
                        //extract attributes from the KML Layer//
                        extractAttributes: true
                    })
                })
            });

2)

设置KML图层的URL:

//note that I have host equal to location//   //Math.Random will stop caching//
var mykmlurl = 'http://' + host + '/KML?key=' + Math.random();

3)

设置图层刷新的时间间隔:

           //function called// //timer// //layer to refresh//
window.setInterval(UpdateKmlLayer, 5000, MyKmlLayer);
更新图层的函数:
            function UpdateKmlLayer(layer) {
                //setting loaded to false unloads the layer//
                layer.loaded = false;
                //setting visibility to true forces a reload of the layer//
                layer.setVisibility(true);
                //the refresh will force it to get the new KML data//
                layer.refresh({ force: true, params: { 'key': Math.random()} });
            }
希望这能让其他人更容易理解。

2
很想知道为什么这个问题会被评为-1。我提出了一个问题,4天后自己找到了解决方案并进行了更新。请解释一下为什么帮助Stack Overflow社区值得被踩? - Sphvn
2
为什么不使用OpenLayers.Strategy.Refresh (http://dev.openlayers.org/apidocs/files/OpenLayers/Strategy/Refresh-js.html) 而不是固定的策略?它正是为您的目的而设计的。 - fbuchinger
1
我正在使用刷新功能。其余部分是为了解决跨浏览器(IE/FF/Chrome/Safari/Opera)的缓存问题... 并且将其放在函数中的原因是可以调用多次以适用于多个图层。设置可见性为 true 可以强制其重新加载,即使在 IE7- 中它决定正常缓存。 - Sphvn
1
它可能被投票否决了,因为您编辑了原始问题,现在还有问题吗?它假装是一个“如何”之类的东西。即使您编辑了问题,也要留下您的问题,让它保持为一个问题。 - capdragon
这个可行!建议在动态KML图层刷新时使用loadend事件监听器。请参见下面的答案。 - tony gil

2

注意:虽然@Lavabeams的方法完美地运作(我已经成功地按照我的需求进行了调整),但是KML图层加载并不总是能够完成。显然,这取决于您的动态KML解析需要多长时间,图层刷新过程会超时并认为该图层已加载。

因此,在添加图层到地图之前,建议使用一个加载事件监听器来检查实际加载的内容是否符合预期。

以下是一个非常简单的检查:

var urlKMLStops = 'parseKMLStops12k.php';         
var layerKMLStops = new OpenLayers.Layer.Vector("Stops", {
            strategies: [new OpenLayers.Strategy.Fixed({ preload: true })],
            protocol: new OpenLayers.Protocol.HTTP({
                url: urlKMLStops,
                format: new OpenLayers.Format.KML({
                    extractStyles: true, 
                    extractAttributes: true,
                    maxDepth: 2
                })
            })
        });

layerKMLStops.events.register("loadend", layerKMLStops, function() {
                var objFs = layerKMLStops.features;
                if (objFs.length > 0) {
                    alert ('loaded '+objFs.length+'  '+objFs[0]+'  '+objFs[1]+'  '+objFs[2]);
                } else {
                    alert ('not loaded');
                    UpdateKmlLayer(layerKMLStops);
                }
            });

使用动态kml层刷新时,有时可能只会得到部分结果,因此您可能还想检查加载的要素数是否等于预期要素数。
注意:由于此监听器循环,使用计数器限制重新加载尝试的次数。
附注:您可能还想通过使用以下内容将图层刷新变为异步任务:
setTimeout(UpdateKmlLayer(layerKMLStops),0);

以上代码在最新版Chrome 20.01132.47上能够正常运行,但如果您同时使用setTimeout调用各种函数(以加载多个动态KML层[跟踪、停留、POI]),则无法在Firefox 13.0.1上正常运行。
编辑:几个月后,我对这个解决方案并不完全满意。因此,我创建了两个中间步骤来确保加载所有数据:
1. 不直接拉取PHP文件,而是让PHP KML解析器保存一个KML文件。然后我使用一个简单的PHP读取器来读取此文件。
为什么这样做更好:
等待PHP文件解析为KML层的源,往往会超时。但是,如果您将PHP解析器作为AJAX调用,则它变成同步的,并且您的代码会等待PHP解析器完成其工作,然后再刷新该层。
由于当我刷新时,KML文件已经被解析并保存,因此我的简单PHP读取器不会超时。
此外,由于您不必循环遍历该层多次(通常第一次就成功了),即使处理时间较长,也可以在第一次完成任务(通常情况下——我仍然检查是否已加载功能)。
<?php
session_start();

$buffer2 ="";
// this is for /var/www/ztest
// for production, use '../kmlStore
$kmlFile = "fileVault/".session_id()."/parsedKML.kml";
//echo $kmlFile;
$handle = @fopen($kmlFile, "r");
if ($handle) {
    while (($buffer = fgets($handle, 4096)) !== false) {
    $buffer2 .= $buffer;
    }
    echo $buffer2;
    if (!feof($handle)) {
    echo "Error: unexpected fgets() fail\n";
    }
    fclose($handle);
}

?>

1
我的回答比较旧,但现在这个更好了。已更新。 - Sphvn

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接