Deck.gl: Per-feature z-index

Created on 3 Dec 2020  路  4Comments  路  Source: visgl/deck.gl

Target Use case

When dealing with a single layer with multiple features (like points in an MVT for example), you might want to draw some of those features on top of others interactively

Proposed feature

Have a getZIndex or similar function that can be defined per feature similar to how getRadius or getFillColor are implemented in some layers

To Do List

  • [ ] Add label and assign to milestone
  • [ ] Coding
  • [ ] Doc update
  • [ ] What鈥檚 new update
  • [ ] Test
feature

Most helpful comment

You can add the small z shift in most layers' getPosition accessor. GeoJsonLayer hides the accessor with an implementation to the GeoJSON spec. If your tiles contain only points, you can always supply your own renderSubLayers:

new MVTLayer({
  ...
  renderSubLayers: props => new ScatterplotLayer({
    getPosition: (f, {index}) => f.geometry.coordinates.concat(index * 0.001),
    ...
  });
});

All 4 comments

There is no concept of "z-index" in deck.gl. In instanced rendering, the features are drawn in parallel, instead of a sequential order. It is possible to add a small depth shift to each geometry to achieve that effect, however it may interfere with the actual 3d depth. We are unlikely able to add this as a generic feature. It will have to be applied on a case-by-case bases.

Thank you for your answer, I can see how that might be a problem.
I've seen some issues saying that points support 3d coordinates where the first two coords are the latitude and longitude pair and the third one a height.
Do you think what I'm asking could be done providing a geometry transform function to the layer that's called per geometry vertex before rendering? I'm thinking about leaving both x and y coordinates the same but changing the z one to move a feature up and down. That would effectively result in what I want.

You can add the small z shift in most layers' getPosition accessor. GeoJsonLayer hides the accessor with an implementation to the GeoJSON spec. If your tiles contain only points, you can always supply your own renderSubLayers:

new MVTLayer({
  ...
  renderSubLayers: props => new ScatterplotLayer({
    getPosition: (f, {index}) => f.geometry.coordinates.concat(index * 0.001),
    ...
  });
});

For documentation purposes in case somebody wants to do the same using an MVT layer and arrives here. The following code works:

new MVTLayer({
  ...
  renderSubLayers: (props) => {
    return new ScatterplotLayer({
      ...props,
      getPosition: (f, index): => {
        const z = index * 0.01
        return [
           ...f.geometry.coordinates,
          z
        ]
      }
    })
  }
}

Notice that, as we are passing the props from the MVTLayer to the ScatterplotLayer, it inherits the modelview matrix and the coordinate system origin and we can use the data fetched by the MVT layer as is. If, otherwise, we don't pass the MVTLayer props to the ScatterplotLayer, we will need to convert the MVT data coordinates to world coordinates.

Was this page helpful?
0 / 5 - 0 ratings