Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Per-feature z-index #5216

Closed
5 tasks
ibesora opened this issue Dec 3, 2020 · 15 comments
Closed
5 tasks

Per-feature z-index #5216

ibesora opened this issue Dec 3, 2020 · 15 comments
Labels

Comments

@ibesora
Copy link

ibesora commented Dec 3, 2020

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’s new update
  • Test
@ibesora ibesora added the feature label Dec 3, 2020
@Pessimistress
Copy link
Collaborator

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.

@ibesora
Copy link
Author

ibesora commented Dec 3, 2020

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.

@Pessimistress
Copy link
Collaborator

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),
	...
  });
});

@ibesora
Copy link
Author

ibesora commented Dec 9, 2020

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.

@amandakoster
Copy link

Hello All,

Happy to have found this example. However, I am using a GeoJsonLayer which does not have the accessor getPosition. GeoJsonLayer does render the following sublayers: SolidPolygonLayer, PathLayer and ScatterplotLayer. Of these, only ScatterplotLayer has the getPosition accessor. How would I add a z-index to Scatterplot subLayer of a GeoJsonLayer?

Thanks in advance! Amanda

@Anand2489
Copy link

@amandakoster you can try getpolygonoffset to offset complete layer along the z-axis. It's a base layer property, so should solve your case too

@jzzfs
Copy link

jzzfs commented May 1, 2023

@amandakoster what worked for me in my GeoJsonLayer was to sort the data so that the features that need to be "on top" are rendered last.
This applies both to the initial render and all subsequent re-renders — e.g. in an onHover callback.

@chriszrc
Copy link

chriszrc commented Jul 5, 2023

@jzzfs @Anand2489 @Pessimistress I have an MVTLayer with pointType: "circle+text" and the circles overlap correctly, but not the text labels:

Screenshot 2023-07-05 at 11 12 26 AM

Any ideas of how to rectify this?

@jzzfs
Copy link

jzzfs commented Jul 10, 2023

@chriszrc I suppose you'll have to split the layers into circles & text.

@chriszrc
Copy link

@jzzfs I originally did split the layers, but then the labels are still on top of everything :(

@tomeronen
Copy link

@jzzfs can you give an example of how you sorted the data in the GeoJsonLayer?

@jzzfs
Copy link

jzzfs commented Jul 18, 2023

@tomeronen sure:

const data = [...];

const sortByLineMembers = () => {
  return data.features
    .slice()
    .sort((f1, f2) =>
      isLineNameSimilar(f1.properties.name) ||
      isLineNameSimilar(f2.properties.name)
        ? 1
        : -1
    );
};

const lines = new GeoJsonLayer({
  id: 'subway-lines-layer',
  data: sortByLineMembers(),

  pickable: true,
  ...
});

Shameless plug: this is taken from my Google Maps Handbook.

@gabrielmilitaruwebmarc
Copy link

@chriszrc did you manage to fix the issue? I have the same problem.

@chriszrc
Copy link

@gabrielmilitaruwebmarc nope 😥

@alonzoalden
Copy link

alonzoalden commented Feb 15, 2024

@chriszrc I'm wondering the same thing, been trying to figure this out for several months now.

I found this older thread: #5672

Apparently setting a text-background, or setting a "z" position on the text position array worked, but I have not been successful when trying either.

Have you found anything new?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

9 participants