From 7e3a8a1050f5b73fe31c13b8fdb02827c493e21b Mon Sep 17 00:00:00 2001 From: Sebastian Date: Mon, 6 Nov 2023 12:59:40 +0100 Subject: [PATCH] Render prune tiles more aggressively. Also prune tiles at different zoom levels either when all tiles at target level are available or if they would be off-screen. --- lib/src/layer/tile_layer/tile_layer.dart | 47 ++++++++++++++++-------- 1 file changed, 32 insertions(+), 15 deletions(-) diff --git a/lib/src/layer/tile_layer/tile_layer.dart b/lib/src/layer/tile_layer/tile_layer.dart index a3c031b76..431a6cd90 100644 --- a/lib/src/layer/tile_layer/tile_layer.dart +++ b/lib/src/layer/tile_layer/tile_layer.dart @@ -1,4 +1,5 @@ import 'dart:async'; +import 'dart:collection'; import 'dart:math'; import 'package:collection/collection.dart' show MapEquality; @@ -25,6 +26,7 @@ import 'package:flutter_map/src/layer/tile_layer/tile_update_transformer.dart'; import 'package:flutter_map/src/map/camera/camera.dart'; import 'package:flutter_map/src/map/controller/map_controller.dart'; import 'package:flutter_map/src/misc/bounds.dart'; +import 'package:flutter_map/src/misc/point_extensions.dart'; import 'package:http/retry.dart'; import 'package:logger/logger.dart'; @@ -531,23 +533,38 @@ class _TileLayerState extends State with TickerProviderStateMixin { ), ); - final currentPixelOrigin = Point( - map.pixelOrigin.x, - map.pixelOrigin.y, - ); - _tileScaleCalculator.clearCacheUnlessZoomMatches(map.zoom); - // Note: We're filtering out tiles off screen. However, we could be smarter, - // e.g. filter out images at non-primary `tileZoom` level that will be covered - // completely by tiles at primary zoom level. + // Note: We're filtering out tiles that are off screen and all tiles at a + // different zoom level but only if all tiles at the target level are ready + // to display. This saves us render time later. + bool allTilesAtTargetZoomLevelReady = true; + for (final tile in _tileImageManager.tiles) { + if (tile.coordinates.z == tileZoom) { + allTilesAtTargetZoomLevelReady &= tile.readyToDisplay; + } + } + + final otherVisibleTileRanges = HashMap(); final tiles = _tileImageManager.tiles - .where((tile) => - visibleTileRange.contains(tile.coordinates) || - // Let tiles with different zoom levels be collected by the pruning - // which also looks at whether the tiles with the target zoom level - // are ready already. - tile.coordinates.z != tileZoom) + .where((tile) { + final c = tile.coordinates; + final zoom = c.z; + + if (zoom != tileZoom && allTilesAtTargetZoomLevelReady) { + return false; + } + + final visibleRange = (zoom == tileZoom) + ? visibleTileRange + : (otherVisibleTileRanges[zoom] ??= + _tileRangeCalculator.calculate( + camera: map, + tileZoom: zoom, + )); + + return visibleRange.contains(c); + }) .map((tileImage) => Tile( // Must be an ObjectKey, not a ValueKey using the coordinates, in // case we remove and replace the TileImage with a different one. @@ -556,7 +573,7 @@ class _TileLayerState extends State with TickerProviderStateMixin { map.zoom, tileImage.coordinates.z, ), - currentPixelOrigin: currentPixelOrigin, + currentPixelOrigin: map.pixelOrigin, tileImage: tileImage, tileBuilder: widget.tileBuilder, ))