Back to Deck Gl

RFC: Improved Customization of Composite Layers

dev-docs/RFCs/v6.4/composite-layer-customization-rfc.md

9.3.24.4 KB
Original Source

RFC: Improved Customization of Composite Layers

  • Authors: Ib Green, Xiaoji Chen
  • Date: Jan 2019
  • Status: Draft

Motivation

deck.gl has strong support for customizing primitive layers, for instance through subclassing and modifying shaders. But things get harder when those shaders are access through a composite layer.

Proposal: CompositeLayers document which sub layers they render

Each composite layer will be expected to document names for its sublayers. This makes it possible for applications to specify overrides for particular layers.

There are two types of naming possible

  • name the actual layer types being rendered: Scatterplot, Path, Polygon in the case of GeoJSON
  • name the actual layer instances being rendered (Points, Lines, PolygonOutlines, ExtrudedPolygons, ...)

QUESTION - Pick one of these schemes, or support both?

Proposal: CompositeLayers take a new prop transferAllProps

  • Currently composite layers carefully pick what props to forward.
  • This was done deliberately to ensure a more rigid interface specification for layers.
  • When replacing sublayers with custom layers, it can be critical to be able to supply a new prop.

The forwardBaseLayerProps() method could check for transferAllProps

Proposal: CompositeLayers take a new subLayerProps prop

The subLayerProps prop would be a recursive object. The keys are sublayer ids and the values are object of props to override. A special prop type can be used to override the default layer constructor.

In application:

js
const customizedGeoJsonLayer = new GeoJsonLayer({
  ...,
  transferAllProps: true,
  subLayerProps: {
    points: {
      type: ExtendedScatterplotLayer,
      extendedProp: 100
    },
    'polygons-fill': {
      subLayerProps: {  // Recursive application of sublayerProps!
        fill: {
          type: HollowPolygonLayer
        }
      }
    }
  }
})

Changes to the CompositeLayer API

getSubLayerProps

The overriding props supplied by the user can be merged inside compositeLayer.getSubLayerProps so that each layer does not have to implement their own handling of subLayerProps.

getSubLayerClass

A new CompositeLayer class method that extracts the type field from subLayerProps, if any. This will replace the ad-hoc implementations in e.g. HexagonLayer and GeoJsonLayer.

Open Questions

Should keys be layer class name or sublayer id?

Composite layers may render multiple sublayers of the same type. For example, the GeoJsonLayer renders two PathLayer instances, one for polygon outlines and one for line strings. Differentiating them with unique ids would give the user finer grain control.

How do user props merge with props created by the parent layer?

In getSubLayerProps, external overriding props supplied via subLayerProps always override those generated by the composite layer.

As a general rule, all sublayer props should be kept overridable. However, layers can prevent override of props using the following mechanism:

js
renderLayers() {
  const SubLayer = new this.getSubLayerClass('child-layer', ScatterplotLayer);
  return new SubLayer(
    // where subLayerProps are merged in
    this.getSubLayerProps({
      id: 'child-layer',

      // "overridable" props
      stroked: this.props.stroked,
      filled: this.props.filled
    }),
    {
      // "non-overridable" props
      data: this.state.data,
      getPosition: d => d.point
    }
  );
}

In this case, the "non-overridable" props are the ones generated internally by the parent layer (e.g. the aggregated data in a HexagonLayer), as well as the accessors that target that specific format. These are considered private implementation of the composite layer, never documentated and may change between patch releases, therefore preventing the users from overriding them is reasonable.

Creating new Layers by overriding sublayers in an existing composite Layer

It is possible to use this mechanism to creating a new layer by overriding layer props in an existing composite layer. In this case, the resulting sublayers would not be overridable. If an overridable layer is desired, the original composite layer will need to be extended into a new class.