TileLayer method to swap tiles while minimising flicker
See original GitHub issueIs your feature request related to a problem? Please describe. Sometimes want to cause the tiles to update, but .redraw() causes all tiles to be removed, and readded. This is undesirable, as causes a very visible flicker to the user, they see all the content disappearing, only to be re added slightly layer. Its made worse because new tiles loaded can ‘animate’ (think 200ms opacity animation)- when they appear. (so even if in browser cache, there is still a delay!)
Describe the solution you’d like Would like to be able to trigger an update of the tile, and for the new tiles to seamlessly replace the old ones.
- Firstly by only replacing the the image once the new tile is retrieved from server. (so swap can be quick!)
- Not animating the tile replacement, as it’s a swap/update, not a new layer. (or at least if animating, be a ‘cross-fade’. Not a 0-100% opacity animation. )
I think a .refresh()
method for TileLayer will do it. So if using a ‘callback’ in the URL template, the callback will be reevaluated. Or can call .setURL(url, false)
to prevent the automatic redraw, and call .refresh()
instead.
This new would simply loop through all the visible tiles, reevaluate the url template, if changed load the new tile in background, and then swap it with old visible tile. Making sure to not trigger the opacity animation.
Describe alternatives you’ve considered
I have a working implementation that uses jQuery (for the lazy) to loop through the actual <img>
in the map and updating the .src
attribute directly!
Does two extra things,
- first loads the tile in a
Image
Object, and only updates the actual<img>
after loading. (so the swap happens when the new tile is already in browser cache!) - temporarily disables map animation. I can’t figure out how to update the .src on the without its onload event firing, which triggers the animation!)
Additional context
Can see demo here: https://www.geograph.org/leaflet/viewpoint.php#17/53.22078/-4.16515 Toggle on the ‘Subject Dots’ layer, the ‘View’ layers (if visible are ‘redrawn’) The view layers are available in both ‘purple marker’ or ‘purple marker + line’ the line is only on if ‘Dots’ layer enabled.
For comparison, a version just using native redraw()
method
https://www.geograph.org/leaflet/viewpoint-redraw.php#17/53.22078/-4.16515
see if togging Dots, can see all the purple markers disappear, and then reappear. Even if the tile is in browser cache.
And the relevant code: https://gist.github.com/barryhunter/437b661faa92174eb45a9f578fec4512
Will give it a go as new method in https://github.com/Leaflet/Leaflet/blob/master/src/layer/tile/TileLayer.js but thought should open here first to see if anyone has any ideas.
Saw https://github.com/Leaflet/Leaflet/issues/6158 but that is about preventing flicker when not updating the tile, I want to prevent flicker when updating tile URL!
Issue Analytics
- State:
- Created 4 years ago
- Reactions:5
- Comments:27 (11 by maintainers)
Top GitHub Comments
Oh, sorry about the demo, a upstream dependency (unrelated to the actual problem) has moved! Will update that.
In theory would just include the code, https://gist.github.com/barryhunter/e42f0c4756e34d5d07db4a170c7ec680
then
ie tileLayer2 ‘extends’ the normal tileLayer, and adds functions, but otherwise its use is the same.
The added true on the
setUrl
is to disable the internalredraw
function. Don’t want that, as its the one that has the ‘flicker’.But then you need to explicitly call the (new)
refresh
method, which does the (hopefully) graceful reload of tiles.… do remember this still a ‘bodge’. The refresh method messes with the main maps ‘Animated’ setting (because couldnt figure how to disable the animaton only on the specific tiles (or even just the tilelayer)) - if call refresh too quickly, it can end up that animation remains turned off completely!
I am surprised this does not have more attention. I feel like it’s an important problem to fix.
@barryhunter is your fix still up to date? Did you make it a plugin?