When there are multiple Views, a TileLayer inside one View is always affected by viewport of other view.
For example, (I will try to create a runnable one if necessary)
const views = [
new OrbitView({ id: "v0", width: "50%" }),
new OrbitView({ id: "v1", x: "50%", width: "50%" })
];
const layers = [
new TileLayer({
id: "v0-tile",
renderSubLayers() {
return new BitmapLayer(...);
}
})
];
const layerFilter = ({ layer, viewport }) =>
layer.id.startsWith(`${viewport.id}-`);
<DeckGL views={views} layers={layers} layerFilter={layerFilter} />;
The TileLayer intends to be shown in v0 only.
But this does not work well, since layerManager.activateViewport() sets current viewport to viewport v0 and v1 alternatively. When viewport v1 is applied, the layer is rendering using the incorrect zoom level and tile indices, which causes tiles loading or disappearing.
This situation could be fixed partially by limiting TileLayer to only react to v0:
class MyTileLayer extends TileLayer {
shouldUpdateState(params) {
if (params.context.viewport.id !== 'v0') return false;
...
}
_updateTileset() {
if (this.context.viewport.id !== 'v0') return false;
...
}
}
However, the workaround does not solve the root issue that changeFlags.viewportChanged is true when layerManager.activateViewport() detects a change of viewport from v1 to v0, and provides it to TileLayer, even if only props change.
This causes that, when TileLayer.updateState() is invoked, the line inside the following if clause is invoked incorrectly, as changeFlags.viewportChanged is true:
if (createTileCache || changeFlags.viewportChanged) {
this._updateTileset();
}
Any suggestions? Thanks!
Yes this is a general issue with our tile layers including 3D tile layers. Probably not helpful for the short term fix, but for the longer term it would probably make sense to have a tileset update/traverse operation that accepted multiple view frustums for tile selection.
Thanks for reporting. We should respect layerFilter in setting the viewportChanged flags. I will look into a fix.
The above PR is landed in 8.2.0-beta.2
@Pessimistress Thanks! It works like a charm.
I have also checked the invocations of TileLayer.shouldUpdateState and TileLayer._updateTileset:
TileLayer.shouldUpdateState, sometimes the other viewport is provided in params.context, but the viewportChanged is correctly set to false. It happens occasionally when propsChanged such as props.visible changed deeply.TileLayer._updateTileset is called with the context.viewport set to other viewports. With more views, the situation increases like following. This does not happen after initial loading, also it seems do not affect rendering, by either ignoring or manually skipping the invocation.
Fixed by [email protected] Thanks for the working!