Select to view content in your preferred language

How to customize a TileLayer with a custom source and support client-side rendering

813
1
02-16-2022 03:26 PM
RyanSutcliffe
Frequent Contributor

I would like to create a custom TileLayer for my ArcGIS JavaScript API based application. My requirements are that it consumes tiled data from a specific non-ArcGIS Server source and that I can update the way the data is rendered-- clientside.

I looked first at the BaseTileLayer Class and the examples there rendering a Custom Lerc Layer in 2D.

That shows how you can override fetchTile() method to process data just after it is fetched and before it is displayed in view. Works well. But what if I want rerender the layer in my 2d/3d View based on an event clientside? Eg. I want behavior like this old example with an ImageryTileLayer where the color scheme can be adjusted, no new data fetching involved.

I see that it there is a blurb in the Layer Class API page for each layer type and for BaseTileLayer it says:

No editing, client-side rendering, or popup templates; some schema limitations in 3D views.

Is that the end of the story then? Because I also know that custom LayerView Classes(BaseLayerView2D, BaseLayerViewGL2D) exist to handle custom rendering of clientside data on various events. Even if my solution is limited to 2D Views, this seems what I would want. 

Does anyone have any ideas? This is pretty critical to our business needs so I want to make sure I am clear on the limitations and my answer back to my team.

What I tried

I tried adding a createLayerView method to the extended BaseTileLayer class instance in this Custom Lerc Layer example. and adding my own BaseLayerView2D instance as the LayerView similar to what was done here in this WebGL Example. This causes fetchTile() to not fire. I see that the API says that createLayerView is used internally and should not need to be customized-- yet the ArcGIS Custom LayerView examples do exactly that.

0 Kudos
1 Reply
RyanSutcliffe
Frequent Contributor

Update:

After some help from an ESRI Canada support analyst I came up with a preliminary solution. Instead of trying to manipulate the LayerView via createLayerView as I mentioned above, I create my customTileLayer with a color property that I can alter. When I fire an event to change that property I also call the `.refresh` method on the baseTileLayer. This redraws the layer. The browser is smart enough to recognize that tiles will have already been fetched so the update is faster. You can see that in action in this codePen here. Note that I also toggle the layer visible on and off to help ensure the screen is completely redrawn.

This is okay but there are problems. The redraw here is a bit slow. I've since tested an approach where my customTileLayer class stores (caches) the processed tileData as a property and this seems to be faster. To mitigate problems with bloating memory size I use an LRUCache to limit the amount/size of cached tiles. I don't have a codePen of that, but you can see a rough working example in GitHub here.

the other problem is that sometimes, especially if you are zooming or panning, we see the old style stick around or flash. I've tried making the fetch calls within fetchTile cancellable with using an AbortSignal for esriRequest. I couldn't quite fix the problem with that. Instead I've been experimenting with only allowing style updates when the layer is stationary which seems to help and is acceptable UX for my purposes.

0 Kudos