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

feat: absolute draw order / rank property #4676

Closed
gvwilson opened this issue Jul 17, 2024 · 6 comments
Closed

feat: absolute draw order / rank property #4676

gvwilson opened this issue Jul 17, 2024 · 6 comments
Assignees
Labels
cs customer success feature something new

Comments

@gvwilson
Copy link
Contributor

gvwilson commented Jul 17, 2024

Currently, there is no way to set an absolute draw order for traces. It would be very useful to have a property to determine the global draw order, e.g. to give a trace the value of 1 to make sure it is always drawn on top of all other traces and another trace the value of 9999 to make sure it is drawn behind all other traces.

@gvwilson gvwilson added feature something new cs customer success labels Jul 17, 2024
@gvwilson gvwilson self-assigned this Jul 17, 2024
@gvwilson
Copy link
Contributor Author

Let me break down the current behavior a little:
(0) in SVG, there's no concept like z-index in HTML; items later in the DOM are always on top of items earlier in the DOM.
(1) if you have multiple sets of x or y axes overlaying each other, all the traces on the same axes are grouped together and either in front or behind other axes. I would need to verify the details, but I believe higher-index x axes are in front, and for the same x axis higher-index y axes are in front, ie x2y2>x2y>xy2>xy.
(2) Traces of different type have a fixed order, as we put them all in different "layer" groups:

    traceLayerClasses: [
        'imagelayer',
        'heatmaplayer',
        'contourcarpetlayer', 'contourlayer',
        'funnellayer', 'waterfalllayer', 'barlayer',
        'carpetlayer',
        'violinlayer',
        'boxlayer',
        'ohlclayer',
        'scattercarpetlayer', 'scatterlayer'
    ],

Meaning scatter traces are always on top, image traces are always on bottom, everything in between is as in this list.
(3) After that, traces of the same type are ordered by their index in data.

So with all of that in mind, which of these three categories describes your use cases?

It would be fairly easy to add an attribute to change (3) - the ordering of traces of the same type on the same axes, but hard to add a way to change the other orderings (different types, or on different axes).

But there's a workaround: make extra axes - that can be set to be overlaying and matching the main axes and with all their marks disabled, so really their only effect is to change the layering - and put the traces intended to be in back on lower-numbered axes, traces in front on higher-numbered axes.

@gvwilson
Copy link
Contributor Author

The scenario we encountered is in the area of (1). We have scatter traces linked to yaxis2 and bar traces linked to yaxis1. The scatter traces should be drawn on top of the bar traces. From your explanation, the best solution would be to add additional axes with higher indexes (e.g. yaxis3) and re-assign the bar traces to these.

We simplified the axis logic for our less technical end users as follows:

  • There are only two y-axes, one left and one right.
  • There are only two x-axes, one top and one bottom.
  • There is a rank parameter on each trace object, which specifies the global drawing order for the traces.

We could build a workaround on our side that would be invisible to the user by automatically creating multiple axes based on the rank parameter under the hood. However, I feel like such a property could be useful to the plotly community at large and it would probably be easier for you guys to implement than for us.

To summarize:
It would be great, if the rank property on the traces would cover (1), (2) and (3) of your list above.

@gvwilson
Copy link
Contributor Author

gvwilson commented Jul 17, 2024

Summing up past discussions of solution design for this one.

API

  • Add zindex property to cartesian traces, which accepts an integer
  • Traces of higher zindex are drawn on top of traces of lower zindex (consistent with CSS convention)
  • Questions
    • Property name and stacking direction -- i.e. are lower or higher numbers drawn on top? I like following an existing convention for simplicity but open to other conventions
    • Applies to all cartesian traces, or do any need to be excluded?

Implementation (based on notes from @alexcjohnson)

  • Changes to trace drawing logic -- largely within src/plots/cartesian/index.js
  • Separate traces into overlapping sets, i.e. traces that don't overlap each other should be in different sets (different subplots, basically)
  • Figure out stacking order implied by zindex
  • Figure out how many different stacked containers are needed to make the default trace stacking order match the order specified by zindex (Currently, just one container per axis pair is used)
  • Create containers and draw traces in their correct containers
  • Make sure all containers are transformed during zoom/pan rather than just one per axis pair

@gvwilson
Copy link
Contributor Author

See great progress: plotly/plotly.js#6918

@archmoj
Copy link
Contributor

archmoj commented Jul 24, 2024

We could possibly close this one as zorder is implemented. No?

@gvwilson
Copy link
Contributor Author

agreed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
cs customer success feature something new
Projects
None yet
Development

No branches or pull requests

2 participants