Skip to content

fix(deck.gl-geotiff): pass opacity and other inherited props to MosaicLayer sources - #789

Open
kylebarron wants to merge 1 commit into
mainfrom
kyle/mosaic-inherited-props
Open

kylebarron wants to merge 1 commit into
mainfrom
kyle/mosaic-inherited-props

Conversation

@kylebarron

Copy link
Copy Markdown
Member

Note

This PR was written by Claude (Claude Code), not by @kylebarron.

MosaicLayer didn't pass the props a composite layer normally hands its sublayers on to the layers its sources render, so opacity, pickable, parameters, modelMatrix, extensions and the rest had no effect on them. Its inner TileLayer was built from a fixed set of props rather than getSubLayerProps(), and its renderSubLayers called renderSource without the props TileLayer hands it. This builds the inner TileLayer from this.getSubLayerProps(), as deck.gl's TerrainLayer does, and clones each layer renderSource returns with the inherited props it didn't set itself, so a source can still set its own opacity.

Changes

  • Build the inner TileLayer from this.getSubLayerProps(). Its id stays mosaic-layer-${id}.
  • In renderSubLayers, clone each layer renderSource returns (a single layer, null, or nested arrays) with the inherited props TileLayer passes, except those the layer set itself. A layer's own props are the ones passed to its constructor (Object.hasOwn(layer.props, key)), since deck.gl keeps defaults on the props prototype.
  • The inherited keys are the ones getSubLayerProps() returns, less the per-layer id and updateTriggers, so per-tile props like id, data and tile never reach a source's layers.
  • Document the inheritance on renderSource, and comment on why MosaicTileset2DFactory must be a new class on every render: it makes the inner TileLayer pick up new sources and re-render loaded sources with a new renderSource.

Tests

  • opacity on a MosaicLayer reaches a source's layer.
  • A source's layer that sets its own opacity keeps it.
  • A new opacity reaches a source that's already loaded, without fetching it again.
  • opacity reaches every layer in nested arrays a source returns.

Three of the four new tests fail against main. The test that a source keeps its own opacity passes there too; it guards the own-prop rule.

Notes

  • updateTriggers.all on a MosaicLayer now reaches the inner TileLayer, since getSubLayerProps() forwards it, so changing it reloads every source. TerrainLayer drops it by overriding updateTriggers; that's a one-line change if we'd rather not forward it.

Closes #784

🤖 Written by Claude Code

…cLayer sources

MosaicLayer didn't pass on the props a composite layer normally hands its
sublayers, so `opacity`, `pickable`, `parameters`, `modelMatrix`,
`extensions` and the rest had no effect on the layers its sources render.
Its inner TileLayer was built from a fixed set of props rather than
`getSubLayerProps()`, and its `renderSubLayers` called `renderSource`
without the props TileLayer hands it.

Build the inner TileLayer from `this.getSubLayerProps()`, as deck.gl's
TerrainLayer does, keeping its `mosaic-layer-${id}` id. Then clone each
layer `renderSource` returns with the inherited props it didn't set
itself, so a source can still set its own `opacity`. A layer's own props
are the ones passed to its constructor, since deck.gl keeps defaults on
the props prototype. The inherited keys are the ones `getSubLayerProps()`
returns, less the per-layer `id` and `updateTriggers`.

Also say why `MosaicTileset2DFactory` must be a new class on every
render: it is what makes the inner TileLayer pick up new `sources` and
re-render loaded sources with a new `renderSource`.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions github-actions Bot added the fix label Oct 23, 2026

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

MosaicLayer ignores its own opacity and other inherited layer props

1 participant