Old Tiles Remain Drawn with client-side Rendering on BaseTileLayer

1873
5
04-11-2023 10:54 AM
RyanSutcliffe
Occasional Contributor II

I have been working on setting up client-side rendering for Raster-based layers. I've created a customized BaseTileLayer where I can change the filter of the data client-side. However sometimes old tiles of data persist.

Example:

This codepen is a rough example that demonstrates the issue.

artifactIssue.gif

Set threshold to something like 3400. Zoom in a bit. Set threshold to 400. Zoom out. See old filter applied still for certain tiles.

This is not a new issue. I initially noted this problem here in another post. I also posted about similar problems occuring when changing the colors client-side on a renderer for a ImageryTileLayer. 

I've raised the issue to ESRI Technical support but we were unable to resolve the issue. At that time I thought it would be sufficient for my needs to ensure that the MapView was fully drawn and stationary before letting the user adjust the styles. But that turns out not to be acceptable from a client standpoint. 

Does anyone know if there is something that can be done to prevent this while still allowing client-side rendering and adjustments?

0 Kudos
5 Replies
UndralBatsukh
Esri Regular Contributor

HI there, 

I just want to let you know that we improved the behavior of BaseTileLayer to release the tiles that are no longer displayed at 4.27. 

You can test this behavior on our next version. This codepen shows the new behavior:  https://codepen.io/U_B_U/pen/vYVGKwp?editors=1000

 

 

RyanSutcliffe
Occasional Contributor II

I just tested your code pen but I am still able to reproduce the problem I demonstrated above. Or at least there seems to be tiles not drawing correctly. Here is a video:thresholdCacheIssue.gif

0 Kudos
UndralBatsukh
Esri Regular Contributor

Hi there, 

I am not able to reproduce the issue you are seeing. Which browser are you using?

0 Kudos
RyanSutcliffe
Occasional Contributor II

The video was from Firefox. Note that it is import to return to your initial zoom extent. You want to zoom in, say 4x, then zoom back out 4x to return to the initial zoom level. I probably should have added a zoom element displayed in the codepen to show that.

I wasn't able to reproduce the problem every time. If I changed the threshold and waited for a few seconds too long before zooming I did not seem to get the issue. Also note there it looks like there are tiles that aren't drawing at all now whereas my initial example where we'd see the old filtered tile data remain?

At the office here I was eventually able to reproduce the issue (ff) though it too a few tries.

In Chrome the only way I was able to reproduce in the office now, is if I throttle the network speed. Then the problem is really easy to reproduce in your example (missing tiles, not old cached tiles). Try setting the network to 'Fast3G' to see what I mean.


Its certainly tricky though. Let me know if there's anything else I can do. Thanks for looking into.

 

0 Kudos
RyanSutcliffe
Occasional Contributor II

A very late response to an old post, but the trick I recently found that, so far, has gotten around this problem well is to hold off calling .refresh until after the layer has finished loading:

So the setThreshold function in the codepen becomes something like:

function layerCompletelyDrawnAndVisible(layer, view) {
  let [watchUtils] = await loadModules(["esri/core/reactiveUtils"]);
  let layerView = await view.whenLayerView(layer);
  let layerId = await new Promise((resolve) => {
    if (layerView.updating) {
      watchUtils.when(
        () => !layerView.updating,
        () => {
          return resolve(layer.id);
        },
        {
          once: true,
        }
      );
    } else return resolve(layer.id);
  });
  return layerId;
}

function setThreshold() {
    thresholdVal = parseInt(threshold.value);

    let { colors, stops } = getRasterStopsAndColors(
      5000,
      thresholdVal,
      seedColors
    );
    //lercLayer.max = 3000;
    lercLayer.threshold = thresholdVal;
    lercLayer.stops = stops;
    lercLayer.colors = colors;

    //lercLayer.refresh();
    layerCompletelyDrawnAndVisible(lercLayer, view).then(v => lercLayer.refresh())
  }
  // @ts-ignore
  threshold.addEventListener("change", setThreshold);

that seems to deal with the problem nicely!

 

0 Kudos