'Update/Reload specific tile in leaflet dynamicly
If my server tells the clients when and what tile to reload/update, how can reload/update the tile sent from the server? I'm using the L.CRS.Simple
CRS. And I have no zoom levels on a custom game map.
Here is my code:
var map = L.map('map', {
crs: L.CRS.Simple,
attributionControl: false
}).setView([0, 0], 2)
L.tileLayer('/chunks/{x}.{y}.png', {
maxNativeZoom: 1,
minNativeZoom: 1,
}).addTo(map)
function ReloadTile(x,y){
// UPDATE TILE HERE Request for example /chunks/{1}.{1}.png depending on input
}
Solution 1:[1]
First, listen to the tileload
and tileunload
events of the L.TileLayer
to grab references to tiles as they load (and free those references as they unload), e.g.
let myTileLayer = L.tileLayer(...);
let tileRefs = {};
myTileLayer.on('tileload', function(ev) {
tileRefs[ ev.coords.x + ',' + ev.coords.y ] = ev.tile;
});
myTileLayer.on('tileunload', function(ev) {
delete tileRefs[ ev.coords.x + ',' + ev.coords.y ];
});
...so whenever you want to update a tile, you just have to search for it in the data structure.
Remember that in order to reload a HTMLImageElement
, you've got to change its src
property, e.g.:
function ReloadTile(x,y){
const tile = tileRefs[x + ',' + y];
if (!tile) {
// Tile is not currently loaded on the screen
return;
}
tile.src = "/chunks/{1}.{1}.png";
}
Beware of requesting a URL that your browser has cached. Do your homework regarding cache busting and relevant HTTP headers.
Note that I'm using a javascript Object
as key-value data structure, and string concatenation to build up a unique key per tile. You're free to use other data structures (such a Map
) and any other method to index the tiles (such as a double-depth data structure for x-y, or triple-depth for x-y-z, or indexing by tile URL). Also note that the sample code is usign only the X and Y coordinates of the tile since your TileLayer
seems to have only one zoom level.
Solution 2:[2]
lThanks for the help!
My final code:
var map = L.map('map', {
crs: L.CRS.Simple,
attributionControl: false
}).setView([0, 0], 2)
const path = '/chunks/{x}.{y}.png?cash={time}'
const layer = L.tileLayer(path, {
maxNativeZoom: 1,
minNativeZoom: 1,
time: 0
}).addTo(map)
function VectorToString(vector) {
return vector.x + "." + vector.y
}
class TileHandler {
constructor(layer){
this.layer = layer
this.layers = {}
this.layer.on('tileload', (tile) => {
this.layers[VectorToString(tile.coords)] = tile
})
this.layer.on('tileunload', (tile) => {
delete this.layers[VectorToString(tile.coords)]
})
}
update(position){
const tile = this.layers[VectorToString(position)]
const url = L.Util.template(tile.target._url, {
...position,
time: new Date().getTime()
})
if (!tile) return
tile.tile.src = url
}
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | IvanSanchez |
Solution 2 |