Skip to content

[BUG] Seamless Tile Updates w/o Blinking? (not sure if actual bug or not) #2019

@corepuncher

Description

@corepuncher

What is the bug?

Just wanted to explore this a bit more.

Currently, in order to achieve truly seamless updates (say the screen is still, there is an old image URL displaying, and new imagery is available via a new URL), I double up the tile layers like this:

                        // Underlay trickery
                        Opacity(
                              opacity:  frameIndex == 0
                                      ? 1.0
                                      : 0.0,
                              child: TileLayer(
                                // key: !! A dynamic key here destroys the "anti-blink" functionality of this layer
                                urlTemplate:
                                    '${globals.tileRoot}/$tileType/${globals.tileData[tileType]?[0]}/{z}/{x}/{y}.webp',
                                tms: true,
                                minNativeZoom: minNativeZoom,
                                maxNativeZoom: maxNativeZoom,
                                tileDimension: isTile256 ? 256 : 512,
                                zoomOffset: isTile256 ? 0 : -1,
                                tileProvider: _tileProvider,
                                keepBuffer: settings.keepBuffer, //  0,
                                panBuffer: 0,
                                tileDisplay: const TileDisplay.instantaneous(),
                                tileUpdateTransformer: TileUpdateTransformers.debounce(Duration(milliseconds: 128)),
                                evictErrorTileStrategy: EvictErrorTileStrategy.dispose,
                                tileBounds:  tileBoundsE,
                              ),
                            ),

                      // On-Top Image                          
                      Opacity(
                            opacity: frameIndex == 0
                                    ? 1.0
                                    : 0.0,
                            child: TileLayer(
                              urlTemplate:
                                  '${globals.tileRoot}/$tileType/${globals.tileData[tileType]?[0]}/{z}/{x}/{y}.webp',
                              tms: true,
                              minNativeZoom: minNativeZoom,
                              maxNativeZoom: maxNativeZoom,
                              tileDimension: isTile256 ? 256 : 512,
                              zoomOffset: isTile256 ? 0 : -1,
                              tileProvider: _tileProvider,
                              keepBuffer: settings.keepBuffer,
                              panBuffer: settings.panBuffer,
                              tileDisplay: const TileDisplay.fadeIn(),
                              evictErrorTileStrategy: EvictErrorTileStrategy.dispose,
                              tileBounds:  tileBoundsE,
                            ),
                          ),

Thus far, this is the only way I have found to have no blinking or black tiles showing AT ALL.

Now, I was briefly hopeful about using TileDisplay.fadeIn(), because it says:

"Fade in the tile when it is loaded. Not (<--typo) that opacity is not supported when fading is enabled. This is because underlying tiles are kept when fading in a new tile until it is loaded and with a partially transparent tile they are both visible during fading which causes flickering."

So I thought that perhaps because it "keeps" the old image until new is faded in, that I would not need the other TileLayer() underneath. However, I have found that this is not the case, and without the first TileLayer, there is still blinking.

Related to this setup, there are perhaps conflicting properties between the two TileLayer().

For example, although my "on top" (2nd in Z index) layer has a keepBuffer of "settings.keepBuffer", it is the keepBuffer of the FIRST TileLayer() that is actually being respected. Since that is only an underlay layer for reducing blinking, and not really seen much, I originally had keepBuffer "for that layer" at 0. But if I do that, the keepbuffer of the second TileLayer gets overridden. So I wonder if keepBuffer is relative to the tile URL, and since it was already defined in the underlay layer, it does not get "redefined" in the second layer?

I also put a debounce transformer on the underlay layer, since it is not imperative to get it downloaded as fast.

Summary: It appears the only way for seamless transitions/updates is to use 2 of the "same" TileLayer(), and you must match the keepBuffers as well. Using "fadeIn" alone on a single TileLayer still results in some blinking, not sure if that is intended.

How can we reproduce it?

See code above

Do you have a potential solution?

The only solution I have thus for for anti-blinking is to always have 2 TileLayer() for the same urlTemplate.

Platforms

Any platform

Severity

Minimum: Allows normal functioning

Metadata

Metadata

Assignees

No one assigned

    Labels

    needs triageThis new bug report needs reproducing and prioritizing

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions