开发者

Refresh / Redraw a Layer in OpenLayers (KML) Network-Link Auto Refresh

开发者 https://www.devze.com 2023-01-02 10:52 出处:网络
TLDR I want to refresh a layer on a timer so it plots the new kml data (like update-link / network link)

TLDR I want to refresh a layer on a timer so it plots the new kml data (like update-link / network link)


So far I have tried action function as follows:

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

set interval of the function:

   开发者_如何学Python             window.setInterval(RefreshKMLData, 5000, KMLLAYER);

the layer itself:

           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
                   })
               })
           });

the url for KMLLAYER with Math random so it doesnt cache:

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

I would have thought that this would Refresh the layer. As by setting its loaded to false unloads it. Visibility to true reloads it and with the Math random shouldn't allow it to cache? So has anyone done this before or know how I can get this to work?


Figured seen as it was hard enough for me to find information on this I would add this:


1)

Create the KML Layer:

            //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)

Set the URL for the KML Layer:

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

3)

Set the interval in which to refresh your layer:

           //function called// //timer// //layer to refresh//
window.setInterval(UpdateKmlLayer, 5000, MyKmlLayer);

4)

The function to update the layer:

            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()} });
            }

Hopes this makes it easier for some others out there.


ATTENTION: while @Lavabeams' method works perfectly well (i have adapted it to my needs with no problem at all), kml layer loading DOES NOT ALWAYS COMPLETE properly.

apparently, depending on how long your dynamic kml takes to parse, the layer refresh process times out and considers the layer loaded.

therefore, it is wise to also use a loading event listener (before adding layer to map) and check what was effectively loaded and if it matches expectations.

below a very simple check:

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);
                }
            });

with dynamic kml layer refreshing, you might sometimes get only partial results, so you might want to ALSO check if the number of features loaded equals the expected number of features.

words of caution: since this listener loops, use a counter to limit the number of reload attempts.

ps: you might also want to make layer refresh an asynchronous task by using:

setTimeout(UpdateKmlLayer(layerKMLStops),0);

latest browser status on above code: works well on chrome 20.01132.47, not on firefox 13.0.1 if you simultaneously call various functions (to load multiple dynamic kml layers [track, stops, poi's]) using setTimeout.

EDIT: months later, i am not totally satisfied with this solution. so i creted 2 intermediate steps which guarantee that i load all my data:

  1. instead of pulling the php file directly, i make the php kml parser save a kml file. i then use a simple php reader to read this file.

why this works better:

waiting for the php file to parse as a source for a kml layer, often times out. BUT, if you call the php parser as an ajax call, it becomes synchronous and your code waits for the php parser to complete its job, before going on to refresh the layer.

since the kml file has already been parsed and saved when i refresh, my simple php reader does not time out.

also, since you do not have to loop thru the layer as many times (you usually are successful the first time around), even though processing takes longer, it gets things done the first time around (usually - i still check if features were loaded).

<?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);
}

?>
0

精彩评论

暂无评论...
验证码 换一张
取 消