Open ChristopheLyonnaz opened 2 months ago
What happens if you set the maxZoom to 20 as well (or try 19 out of interest as well) ?
Tile is loaded and displayed correctly. But it assumes you know what the max available zoom is, which may not be always true
I'm a bit out of touch on the recovering parent tile code etc, but I suspect this would be quite fiddly to resolve. Lets say you want zoom 30, but only have access to max zoom 20, and are panning, so potentially have no historic higher zooms "cached"...I think you would need to keep lots of old tiles about which would hurt performance, and you may still not have cached tiles to use anyway, so would still hit the same problem...
It seems quite reasonable if adding a URL of a tile provider to know its valid tile range ?
Yes, I agree, that would be easier. But in my specific use case, the tiles are loaded by the end user to have offline maps, and I don't know in advance what max zoom is available for a specific area when building the TileLayer.
However, I don't think it is necessary to 'cache' a lot of tiles. Just like when you manage a supported zoom, you request the missing tile to the server. Here also, if tile at zoom Z+1 is not available, it seems feasible to load tile at zoom Z.
To give more consistency to my latest comment, I did a small check. Let assume my server only provides tiles with max zoom as 10.
If a change _onTileUpdateEvent() in tile_layer.dart as follows:
void _onTileUpdateEvent(TileUpdateEvent event) {
final tileZoom = _clampToNativeZoom(event.zoom);
....
to
void _onTileUpdateEvent(TileUpdateEvent event) {
final tileZoom = _clampToNativeZoom(event.zoom).clamp(widget.minNativeZoom, 10);
...
All is working nicely.
The goal is now to be able to build dynamically the '10' from the server capabilities (or in my case, from the available tile list in the displayed area). And either to delegate this to tile_layer, or to give a way for the TileLayer user to give this information in TileProvider or TileBuilder functions.
Hacky, but could you do something like the following before starting flutter_map to figure the max zoom from the given tiles..
pseudocode
sub figureMaxZoomAvailable { for x 9..30 { ok, error = getUrl ( "https://tile.openstreetmap.org/{$x}/1/1.png") if error, return x-1 }
Yes, I thought of such a solution, but unfortunalely, this is valid only if I have the same zoom level for all the area I want to cover.
If I have tiles up to zoom 10 over France, but up to 9 over US, I will start flutter_map with a TileLayer with maxNativeZoom = 9 if I visit the US, and start a new flutter_map if I visit France.
However, you gave me an idea. I may be able to create 1 TileLayer per area, and load them all in flutter_maps as children. Each TileLayer child would be defined with its maxNativeZoom and with its boundaries.
I'll keep you informed if this work around the issue.
A final word on this issue from my side. I manage to work around this issue, by 'simply' stacking several TileLayers, with boundary limits and maxNativeZoom on each of them. Each TileLayer is defined when maps are downloaded from the server.
In order to make this works correctly, make sure to sort them by max zoom level (from the lowest to the highest).
mapList.forEach((map) {
layers.add(
TileLayer(
urlTemplate: tilesPath,
tileProvider: FileTileProvider(),
maxNativeZoom: map.zoom,
tileBounds: LatLngBounds(map.northWest, map.southEast),
),
);
});
What is the bug?
TileLayer should be able to load tile of lower resolution if the tile provider cannot provide the tile at required zoom.
When TileLayer loads a tile at zoom Z, if the user zooms in, TileLayer gets the tile at zoom Z+1. if the tile provider cannot deliver this tile, or if the maxNativeZoom is defined as Z, TileLayer scales up the latest available tile (at zoom Z) and displays it correctly. However, in this situation (where a tile is scaled up), if the user scrolls to adjacent tiles, TileLayer fails to recover the tile at zoom Z to scale it up and display it at the new position. It returns an error and displays a grey area, or the fallback strategy.
How can we reproduce it?
Create a map layer with a maxNativeZoom greater than the maximum zoom available in your tile provider. Zoom on a area to display a tile with the maximum zoom. Continue zooming to have this tile scaled up. Scroll to adjacent tile.
TileLayer fails to get the adjacent tile and returns an exception:
Here is an example of code (inspired from 'Sliding Map' flutter_map example):
Do you have a potential solution?
Not yet a solution, but I suggest that _onTileUpdateEvent() function may be able to check for max available zoom from provider and updates tileZoom accordingly.
Currently, it only clamps zoom with maxNativeZoom, but this clam can be adjusted according to server capability.
Platforms
All Android and iOS plateforms
Severity
Erroneous: Prevents normal functioning and causes errors in the console