-
-
Notifications
You must be signed in to change notification settings - Fork 860
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
(⏸︎) Replace TileLayer.errorImage
with TileLayer.tilePlaceholder
#1587
(⏸︎) Replace TileLayer.errorImage
with TileLayer.tilePlaceholder
#1587
Conversation
@JaffaKetchup / @TesteurManiak / @ibrierley etc this idea came to me so I whipped together a quick implementation. WDYT? A preview: |
Just relating to your last comment, I can't recall exactly the logic (and we may already do something similar, or it may have been removed...) but would it make sense for each new tile to have your placeholder which is switched to the live tile when loaded, but until the live tile is loaded its sorted first in the list of tiles (that way any unloaded tile would automatically be at the back of the display and any previous zoom tiles overlayed in front) Not sure if that's as clear as mud! |
I didn't try that and it may be possible but I suspect when zooming out that will cause the grid to be overlayed over higher-zoom tiles until the new tiles load. I'll have to give it a try to be sure. I've always found the pruning logic tough to reason about, that's probably an area that could really benefit from some dedicated tests to make sure we retain tiles appropriately when zooming. |
Unless I've missed something, it looks like this was already possible through It also looks like the ability to display an error image has been removed? If so, I think the separate error image could be useful. Maybe what this points to is a requirement for the reworking and simplification of the
We then provide a default implementation which just redirects the first 3 statuses to the grid you created, and otherwise just renders the image. |
I think you're right that this can probably be replicated with I've never actually used In any case I definitely agree that this area can be improved and I'm not at all tied to the solution that this PR presents. I'd love to have a better idea of if/how people are using P.S. Tile pruning is still one part of the tile layer which I find quite hard to reason about. The pruning logic depends on various TileImage variables (current/retain/active) and there are complicated requirements around keeping tiles when zooming out until they are covered up by a fully loaded tile in a lower zoom etc. It's a tough problem in general, when I looked at Google Maps for some inspiration I found bugs in their placeholder image which caused it to flicker or remain visible on top of tiles. |
I was facing the same problem, my workaround is to put lat_lon_grid_plugin behind the tile layer, it's work perfectly |
@mohammedX6 that's definitely a good option! In this case I would like to make it as efficient as possible by only adding placeholders behind tiles which are not completely visible. I will revisit this PR after #1596. |
That's nice idea |
e57f8db
to
08cb80d
Compare
I've updated this to incorporate changes from #1596 and added a simple algorithm which reduces the number of placeholders created. |
TileBounds tileBounds, | ||
) { | ||
TileBounds tileBounds, { | ||
bool Function(TileImage tileImage)? test, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should probably rename this to be clearer what it does (I know it's internal only, but still should have a more self-explanatory name). Perhaps use @visibleForTesting
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not related to testing, it's an optional filter. I followed the naming convention that I've often seen in dart e.g: https://api.flutter.dev/flutter/dart-core/Iterable/where.html
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, that makes more sense. I'm aware that test
is usually the terminology used, but usually the method name itself adds to the context. Maybe it should be filter
or filterTest
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Personally, I still think errorImage
should be kept. I haven't used it myself, but I can think that some people would want a different error image (let's just say https://http.cat for example), instead of a placeholder/loading image (the square grid, for example).
Additionally, would it perhaps make sense to allow placeholderImage
(and errorImage
) to take any Widget
s?
Does this PR make the grid placeholder the default, or is there no placeholder by default? I think the grid being the default makes sense.
PS (unrelated). I'm not sure whether #1563 & #1602 might be related to a bug in the pruning logic? Or whether the bug is somewhere else.
When a tile fails to load and there are no existing loaded tiles which overlay with it from another zoom level we are left with a blank portion on the map. When there are no loaded tiles visible, for example because of a network problem, there is no visual feedback when zooming/panning/rotating because the map is just a single solid color. This prompted me to add a placeholder image. We already have an error image implementation but the error image will not show up until loading fails which, in the case of a poor network connection, can take quite a while. The placeholder implementation gives visual feedback both whilst loading and when loading fails. Note that the current implementation just fills the viewport with the placeholder tile behind all other tiles. It would be more efficient to avoid adding placeholder tiles which are completely obscured by other visual tiles but my attempts to do this were unsuccessful due to the complex nature of tile pruning.
…ansitioned at the current zoom This reduces the number of placeholder widgets. The algorithm used to determine which coordinates to show placeholders for is a tradeoff between speed and the number of redundant placeholders created. It creates a placeholder for every tile at the current zoom which failed to load or is still transitioning. This means that if a tile from a lower zoom obscures the placeholder or multiple tiles from a higher zoom collectively obscure the placeholder it will be unnecessarily created. It would be possible to avoid this but it would require a more complex data structure or iterating all of the tiles for every potential placeholder.
…geProvider for placeholders.
Now that placeholder is a widget instead of an ImageProvider we can simplify the construction by making it a CustomPaint.
653d784
to
6bb5588
Compare
My reasons for removing errorImage are as follows:
For these reasons my inclination would be to remove errorImage, most of all because I suspect that due to points 1 and 3 it is not used and, if it is used, the useful behaviours are more elegantly handled by placeholderImage. It's totally possible that the clunky UI doesn't bother some users and that they will be disappointed if this features is removed, it's really hard to know 🤷 . Given the points I've raised above what is your feeling?
I've made this change and simplified the creation of a placeholder grid tile by moving to CustomPaint since we don't need to generate an ImageProvider anymore. The only downside is that it prevents us from implementing a more efficient way of rendering the placeholders (e.g. rendering them all using a single painter instead of multiple positioned widgets containing painters). That's probably OK given that there are a small amount of them and the performance difference is likely to be insignificant. I've just added a commit which makes this change.
To avoid a breaking change it was disabled by default but I agree that it is a sensible default and I've now made it enabled by default, it can be set to null to disable it.
I haven't tested locally but my first guess after a brief glance would be that a map event is not being triggered by the movement and therefore loading/pruning does not get triggered. |
Would there be a disadvantage to treating it like a non-loaded image?
I'm still in the same mind, but maybe @ibrierley, @TesteurManiak, and @mootw would like to add their opinions :D.
I would agree with this, but I can't understand why the normal way of calling |
Tried to catch up on the discussion, I'd tend to agree with @rorystephenson on removing the I'm always in favor of deprecation, if possible, before removing a property so you can inform the user of its issues and share some code sample to facilitate the transition. In this case, having a "before/after" in the deprecation message and a code sample directly in the code comments would help existing users to adopt the new way of displaying placeholders. |
Just an update. I've recently started a new job and I don't have a lot of extra time to dedicate to this right now. |
@rorystephenson No problem, hope you're enjoying your new job. |
This is now being moved into Draft status, to unblock the v6 release. |
TileLayer.errorImage
with TileLayer.tilePlaceholder
When a tile fails to load and there are no existing loaded tiles which overlay with it from another zoom level we are left with a blank portion on the map. When there are no loaded tiles visible, for example because of a network problem, there is no visual feedback when zooming/panning/rotating because the map is just a single solid color. This prompted me to add a placeholder image.
We already have an error image implementation but the error image will not show up until loading fails which, in the case of a poor network connection, can take quite a while.
The placeholder implementation gives visual feedback both whilst loading and when loading fails.
Note that the current implementation just fills the viewport with the placeholder tile behind all other tiles. It would be more efficient to avoid adding placeholder tiles which are completely obscured by other visual tiles but my attempts to do this were unsuccessful due to the complex nature of tile pruning.