简体   繁体   中英

How to refresh individual tiles in openlayers?

I am trying to build an app which has tiles changing over time. So Far I was able to refresh just the entire tile source. However whenever you refresh it there is a short blink of the entire picture - the picture is deleted and redraw again. However, if the tiles are loading only part of image where the new tile is loaded is redrawn. I would like to get similar behaviour

var Source=new ol.source.OSM({
                url: 'http://localhost:900/{z}-{x}-{y}.png',
                attributions:[],
                wrapX: false    ,
                tileLoadFunction:function(imageTile, src) {var mr = Math.random();    imageTile.getImage().src = src+'?t='+mr;}
            });

plus refreshing:

Source.tileCache.expireCache({});
            Source.tileCache.clear();
            Source.refresh();

It's probably not possible to change the way refresh works without rewriting part of OpenLayers but if you maintain an update timestamp for each tile instead of adding a random value OpenLayers will use browser cache when there is no update required instead of reloading every tile from the server, making a faster refresh so the flicker should be less noticeable. As it will be indexed by tile coordinates it will need to be added in the tileUrlFunction instead of the tileLoadFunction. The OSM constructor doesn't support tileUrlFunction, but XYZ can be used instead.

var startTime = new Date().getTime();
var updateTimes = {};

var source = new ol.source.XYZ({
    attributions:[],
    wrapX: false,
    tileUrlFunction: function(tileCoord) {
        var z = tileCoord[0];
        var x = tileCoord[1];
        var y = -tileCoord[2]-1;
        var timestamp = updateTimes[ z + '_' + x + '_' y ] || startTime;
        return 'http://localhost:900/' + z + '-' + x + '-' + y + '.png?t=' + timestamp;
    }
});

function refresh(x, y, z) {
  updateTimes[ z + '_' + x + '_' y ] = new Date().getTime();
  source.refresh();
}

You might get a further improvement by preloading the new tile to populate the browser cache before refreshing

function refresh(x, y, z) {
  updateTimes[ z + '_' + x + '_' y ] = new Date().getTime();
  var img = document.createElement("img");
  img.onload = function() {
      img.remove();
      source.refresh();
  };
  img.src = 'http://localhost:900/' + z + '-' + x + '-' + y + '.png?t=' + updateTimes[ z + '_' + x + '_' y ];
}

I solved it - you cant refresh entire source, but just remove the tile from the cache:

function RefreshIndividual(z,x, y) {
            var index= z+'-'+x+'-'+y;
            var index2= z+'/'+x+'/'+(-y-1);
            updateTimes[index] = new Date().getTime();
            console.log(index,'t'+updateTimes[index]);
            Source.tileCache.remove(index2);
            Source.changed();

        }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM